/* * RHQ Management Platform * Copyright (C) 2011 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also as published by the Free * Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.rhq.enterprise.server.configuration.util; import org.jetbrains.annotations.NotNull; import org.rhq.core.domain.configuration.AbstractPropertyMap; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.Property; import org.rhq.core.domain.configuration.PropertyList; import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.configuration.definition.PropertyDefinition; import org.rhq.core.domain.configuration.definition.PropertyDefinitionList; import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap; import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple; import org.rhq.core.domain.configuration.definition.PropertySimpleType; import java.util.List; import java.util.Map; /** * A class that provides static methods for masking and unmasking password properties within {@link Configuration}s, * The reason for masking a property's value is so that the current values of such properties cannot be viewed by a * user by viewing the HTML source of a Configuration GUI page, e.g.: * * <input type="password" value="********" .../> * * would be rendered, rather than: * * <input type="password" value="ACTUAL_PASSWORD" .../> * * @author Ian Springer */ public class ConfigurationMaskingUtility { /** * Mask the values of all simple properties of type PASSWORD in the configuration. The properties are masked by * calling {@link PropertySimple#mask()}. The configuration does not need to be normalized; that is, properties * defined by the configuration definition do not need to exist in the configuration. * * @param configuration the configuration to be masked * @param configurationDefinition the configuration definition corresponding to the specified configuration; this is * used to determine which properties to mask - all simple properties of type * PASSWORD at any level within the configuration are masked */ public static void maskConfiguration(@NotNull Configuration configuration, @NotNull ConfigurationDefinition configurationDefinition) { if (configurationDefinition == null) { return; } Map<String, PropertyDefinition> childPropertyDefinitions = configurationDefinition.getPropertyDefinitions(); for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) { maskProperty(childPropertyDefinition, configuration); } } /** * Unmask the values of all masked simple properties of type PASSWORD in the configuration. The configuration does not * need to be normalized; that is, properties defined by the configuration definition do not need to exist in the * configuration. * * @param configuration the configuration to be unmasked * @param unmaskedConfiguration the unmasked configuration that should be used as the reference to unmask the * configuration */ public static void unmaskConfiguration(@NotNull Configuration configuration, @NotNull Configuration unmaskedConfiguration) { Map<String, Property> memberProperties = configuration.getAllProperties(); for (Property memberProperty : memberProperties.values()) { unmaskProperty(memberProperty.getName(), configuration, unmaskedConfiguration); } } private static void maskProperty(PropertyDefinition propertyDefinition, AbstractPropertyMap parentPropertyMap) { if (parentPropertyMap.get(propertyDefinition.getName()) == null) { // If the property doesn't even exist, there's nothing to mask. return; } if (propertyDefinition instanceof PropertyDefinitionSimple) { PropertyDefinitionSimple propertyDefinitionSimple = (PropertyDefinitionSimple) propertyDefinition; if (propertyDefinitionSimple.getType() == PropertySimpleType.PASSWORD) { PropertySimple propertySimple = parentPropertyMap.getSimple(propertyDefinition.getName()); propertySimple.mask(); } } // If the property is a Map, recurse into it and mask its child properties. else if (propertyDefinition instanceof PropertyDefinitionMap) { PropertyMap propertyMap = parentPropertyMap.getMap(propertyDefinition.getName()); PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) propertyDefinition; maskPropertyMap(propertyMap, propertyDefinitionMap); } else if (propertyDefinition instanceof PropertyDefinitionList) { PropertyDefinitionList propertyDefinitionList = (PropertyDefinitionList) propertyDefinition; PropertyDefinition listMemberPropertyDefinition = propertyDefinitionList.getMemberDefinition(); // If the property is a List of Maps, iterate the list, and recurse into each Map and mask its child // properties. if (listMemberPropertyDefinition instanceof PropertyDefinitionMap) { PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) listMemberPropertyDefinition; PropertyList propertyList = parentPropertyMap.getList(propertyDefinition.getName()); for (Property property : propertyList.getList()) { PropertyMap propertyMap = (PropertyMap) property; maskPropertyMap(propertyMap, propertyDefinitionMap); } } } } private static void maskPropertyMap(AbstractPropertyMap propertyMap, PropertyDefinitionMap propertyDefinitionMap) { Map<String, PropertyDefinition> childPropertyDefinitions = propertyDefinitionMap.getMap(); for (PropertyDefinition childPropertyDefinition : childPropertyDefinitions.values()) { maskProperty(childPropertyDefinition, propertyMap); } } private static void unmaskProperty(String propertyName, AbstractPropertyMap parentPropertyMap, AbstractPropertyMap unmaskedParentPropertyMap) { Property property = parentPropertyMap.get(propertyName); if (property == null) { // The property doesn't even exist, so there's nothing to unmask. return; } if (unmaskedParentPropertyMap == null) { // The parent map does not exist in the unmasked config, so no unmasking is possible. return; } if (property instanceof PropertySimple) { PropertySimple propertySimple = (PropertySimple) property; unmaskPropertySimple(propertySimple, unmaskedParentPropertyMap); } // If the property is a Map, recurse into it and unmask its child properties. else if (property instanceof PropertyMap) { PropertyMap propertyMap = (PropertyMap) property; PropertyMap unmaskedPropertyMap = unmaskedParentPropertyMap.getMap(property.getName()); unmaskPropertyMap(propertyMap, unmaskedPropertyMap); } else if (property instanceof PropertyList) { PropertyList propertyList = (PropertyList) property; List<Property> memberProperties = propertyList.getList(); // If the property is a List of Maps, iterate the list, and recurse into each Map and unmask its child // properties. if (!memberProperties.isEmpty() && memberProperties.get(0) instanceof PropertyMap) { PropertyList unmaskedPropertyList = unmaskedParentPropertyMap.getList(propertyList.getName()); if (unmaskedPropertyList != null) { List<Property> unmaskedMemberProperties = unmaskedPropertyList.getList(); for (int i = 0; (i < memberProperties.size()) && (i < unmaskedMemberProperties.size()); i++) { PropertyMap propertyMap = (PropertyMap) memberProperties.get(i); PropertyMap unmaskedPropertyMap = (PropertyMap) unmaskedMemberProperties.get(i); unmaskPropertyMap(propertyMap, unmaskedPropertyMap); } } } } } private static void unmaskPropertySimple(PropertySimple propertySimple, AbstractPropertyMap unmaskedParentPropertyMap) { if (propertySimple.isMasked()) { PropertySimple unmaskedPropertySimple = unmaskedParentPropertyMap.getSimple(propertySimple.getName()); String unmaskedValue = (unmaskedPropertySimple != null) ? unmaskedPropertySimple.getStringValue() : null; propertySimple.setStringValue(unmaskedValue); } } private static void unmaskPropertyMap(AbstractPropertyMap propertyMap, PropertyMap unmaskedPropertyMap) { if (unmaskedPropertyMap == null) { // The map does not exist in the unmasked config, so no unmasking is possible. return; } Map<String, Property> memberProperties = propertyMap.getMap(); for (Property memberProperty : memberProperties.values()) { unmaskProperty(memberProperty.getName(), propertyMap, unmaskedPropertyMap); } } }