/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004-2012], VMWare, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License 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 for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.util.security.SecurityUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
/**
* Holds the configuration for auto-discovered resources auto-approval.
*/
public class AutoApproveConfig {
/**
* Used for getting the platform's auto-approve value.
*/
public static final String PLATFORM_PROPERTY_NAME = "platform";
/**
* The logger for this class
*/
private final static Log LOG = LogFactory.getLog(AutoApproveConfig.class.getName());
/**
* The default name of the auto-approve properties file.
*/
private static final String AUTO_APPROVE_PROPS_FILE_NAME = "auto-approve.properties";
/**
* Loaded from the properties file.
*/
private Properties autoApproveProps = null;
/**
* Creates a new auto-approve configuration instance, providing the name of the agent's configuration folder where
* the auto-approve properties file may exist.
*
* @param agentConfigDirName the name of the folder where the agent keeps it configuration files.
* @param encryptionKeyFileName the name of the file where the encryption key is held.
* @throws IllegalArgumentException if the provided configuration directory isn't valid.
*/
public AutoApproveConfig(String agentConfigDirName, String encryptionKeyFileName) {
// make sure the provided directory name isn't null/empty.
if (StringUtil.isNullOrEmpty(agentConfigDirName)) {
LOG.error("Invalid agent configuration directory name - auto configuration of resources is skipped");
return;
}
// make sure the provided encryption key file name isn't null/empty.
if (StringUtil.isNullOrEmpty(encryptionKeyFileName)) {
LOG.error("Invalid encryption key file name - auto configuration of resources is skipped");
return;
}
// reference the configuration directory and make sure it exists.
File agentConfigDir = new File(agentConfigDirName);
if (!agentConfigDir.exists()) {
LOG.error("Agent configuration directory doesn't exist: " +
agentConfigDir.getAbsolutePath() + "- auto configuration of resources is skipped");
return;
}
// reference the encryption key file and make sure it exists.
File encryptionKeyFile = new File(encryptionKeyFileName);
if (!encryptionKeyFile.exists()) {
LOG.error("Encryption key file doesn't exist: " +
encryptionKeyFile.getAbsolutePath() + "- auto configuration of resources is skipped");
return;
}
// reference the auto-approve properties file (if exists).
File autoApprovePropsFile = new File(agentConfigDir, AUTO_APPROVE_PROPS_FILE_NAME);
// if the file exists then load it.
if (autoApprovePropsFile.exists()) {
// The path to the encryption key file.
String encryptionKeyFilePath = encryptionKeyFile.getAbsolutePath();
// The encryption key.
String encryptionKey;
try {
encryptionKey = PropertyEncryptionUtil.getPropertyEncryptionKey(encryptionKeyFilePath);
} catch (PropertyUtilException e) {
LOG.error("Failed to read the properties encryption key - auto configuration of resources is skipped");
return;
}
this.autoApproveProps = loadAutoApproveProps(autoApprovePropsFile, encryptionKey);
LOG.info("Resources auto-approval configuration loaded");
// Make sure all properties are encrypted
ensurePropertiesEncryption(autoApprovePropsFile, encryptionKeyFilePath);
} else {
LOG.info("Resources auto-approval configuration not provided");
}
} // EO Constructor(String)
/**
* Indicates if the agent has auto-approve configuration set.
*
* @return true if the agent was configured for resources auto-approval; false otherwise.
*/
public boolean exists() {
return this.autoApproveProps != null;
} // EOM
/**
* Check if a resource with name <code>resourceName</code> was configured for auto-approval.
*
* @param resourceName the name of the resource to check
* @return true if the resource was marked as auto approve; false otherwise.
*/
public boolean isAutoApproved(String resourceName) {
return resourceName != null && this.exists() &&
Boolean.valueOf(this.autoApproveProps.getProperty(resourceName));
} // EOM
/**
* Get the set of properties that were specified for a resource with name <tt>resourceName</tt>. If the resource
* isn't auto-approved then an empty properties instance is returned. The name of the resource is stripped from the
* property keys.
*
* @param resourceName the name of the resource to get resource for.
* @return a <tt>Properties</tt> instance that were set for the resource. May be empty.
*/
public Properties getPropertiesForResource(String resourceName) {
// Create the result properties.
Properties result = new Properties();
// If the resource isn't auto-approved then return the empty properties.
if (!isAutoApproved(resourceName)) {
return result;
}
// The length of the prefix (used for the stripping).
int prefixLength = resourceName.length() + 1;
// Iterate the properties and collect all with key that start with resourceName.
for (Object keyRef : this.autoApproveProps.keySet()) {
String key = (String) keyRef;
if (!key.equals(resourceName) && key.startsWith(resourceName)) {
result.put(key.substring(prefixLength), this.autoApproveProps.getProperty(key));
}
}
return result;
} // EOM
/**
* Loads the auto-approve properties file.
*
* @param autoApprovePropsFile the properties file to load.
* @return a new <code>Properties</code> instance or null of the reading the file fails.
*/
private Properties loadAutoApproveProps(File autoApprovePropsFile, String encryptionKey) {
try {
// Load the properties from the files system.
Properties result = new Properties();
result.load(new FileInputStream(autoApprovePropsFile));
// Iterate the properties and decrypt if necessary.
for (Object key : result.keySet()) {
// Get the next property.
String keyStr = (String) key;
String prop = result.getProperty(keyStr);
// If the property is encrypted -- decrypt and replace it.
if (SecurityUtil.isMarkedEncrypted(prop)) {
String decryptedProp = SecurityUtil.decrypt(
SecurityUtil.DEFAULT_ENCRYPTION_ALGORITHM, encryptionKey, prop);
result.setProperty(keyStr, decryptedProp);
}
}
return result;
} catch (IOException exc) {
LOG.error("failed to load the properties file", exc);
}
return null;
} // EOM
/**
* Make sure that all the properties in the auto-approve properties file are encrypted.
*
* @param autoApprovePropsFile the properties file to encrypt.
* @param encryptionKeyFilePath the path to the encryption key file.
*/
private void ensurePropertiesEncryption(File autoApprovePropsFile, String encryptionKeyFilePath) {
// Create od Strings keys set
Set<String> encSet = new HashSet<String>(this.autoApproveProps.size());
for (Object key : autoApproveProps.keySet()) {
encSet.add((String) key);
}
// Encrypt.
try {
PropertyEncryptionUtil.ensurePropertiesEncryption(
autoApprovePropsFile.getAbsolutePath(), encryptionKeyFilePath, encSet);
} catch (PropertyUtilException exc) {
LOG.info("Failed to ensure the encryption of auto-approve properties: " + exc.getMessage());
}
} // EOM
}