Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions api/src/main/java/com/cloud/server/ManagementService.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
import org.apache.cloudstack.config.Configuration;
import org.apache.cloudstack.config.ConfigurationGroup;
import org.apache.cloudstack.framework.config.ConfigKey;

import com.cloud.alert.Alert;
import com.cloud.capacity.Capacity;
Expand Down Expand Up @@ -108,14 +107,6 @@
public interface ManagementService {
static final String Name = "management-server";

ConfigKey<Boolean> JsInterpretationEnabled = new ConfigKey<>("Hidden"
, Boolean.class
, "js.interpretation.enabled"
, "false"
, "Enable/Disable all JavaScript interpretation related functionalities to create or update Javascript rules."
, false
, ConfigKey.Scope.Global);

/**
* returns the a map of the names/values in the configuration table
*
Expand Down Expand Up @@ -534,6 +525,4 @@ VirtualMachine upgradeSystemVM(ScaleSystemVMCmd cmd) throws ResourceUnavailableE

boolean removeManagementServer(RemoveManagementServerCmd cmd);

void checkJsInterpretationAllowedIfNeededForParameterValue(String paramName, boolean paramValue);

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
package com.cloud.upgrade.dao;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.exception.CloudRuntimeException;

public class Upgrade42210to42300 extends DbUpgradeAbstractImpl implements DbUpgrade, DbUpgradeSystemVmTemplate {
Expand All @@ -42,4 +47,46 @@ public InputStream[] getPrepareScripts() {

return new InputStream[] {script};
}

@Override
public void performDataMigration(Connection conn) {
unhideJsInterpretationEnabled(conn);
}

protected void unhideJsInterpretationEnabled(Connection conn) {
String value = getJsInterpretationEnabled(conn);
if (value != null) {
updateJsInterpretationEnabledFields(conn, value);
}
}

protected String getJsInterpretationEnabled(Connection conn) {
String query = "SELECT value FROM cloud.configuration WHERE name = 'js.interpretation.enabled' AND category = 'Hidden';";

try (PreparedStatement pstmt = conn.prepareStatement(query)) {
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
return rs.getString("value");
}
logger.debug("Unable to retrieve value of hidden configuration 'js.interpretation.enabled'. The configuration may already be unhidden.");
return null;
} catch (SQLException e) {
throw new CloudRuntimeException("Error while retrieving value of hidden configuration 'js.interpretation.enabled'.", e);
}
}

protected void updateJsInterpretationEnabledFields(Connection conn, String encryptedValue) {
String query = "UPDATE cloud.configuration SET value = ?, category = 'System', component = 'JsInterpreter', is_dynamic = 1 WHERE name = 'js.interpretation.enabled';";

try (PreparedStatement pstmt = conn.prepareStatement(query)) {
String decryptedValue = DBEncryptionUtil.decrypt(encryptedValue);
logger.info("Updating setting 'js.interpretation.enabled' to decrypted value [{}], and category 'System', component 'JsInterpreter', and is_dynamic '1'.", decryptedValue);
pstmt.setString(1, decryptedValue);
pstmt.executeUpdate();
} catch (SQLException e) {
throw new CloudRuntimeException("Error while unhiding configuration 'js.interpretation.enabled'.", e);
} catch (CloudRuntimeException e) {
logger.warn("Error while decrypting configuration 'js.interpretation.enabled'. The configuration may already be decrypted.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import com.cloud.user.UserVO;
import com.cloud.utils.DateUtil;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
Expand Down Expand Up @@ -163,12 +164,6 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {

private Set<Account.Type> accountTypesThatCanListAllQuotaSummaries = Sets.newHashSet(Account.Type.ADMIN, Account.Type.DOMAIN_ADMIN);

protected void checkActivationRulesAllowed(String activationRule) {
if (!_quotaService.isJsInterpretationEnabled() && StringUtils.isNotEmpty(activationRule)) {
throw new PermissionDeniedException("Quota Tariff Activation Rule cannot be set, as Javascript interpretation is disabled in the configuration.");
}
}

@Override
public QuotaTariffResponse createQuotaTariffResponse(QuotaTariffVO tariff, boolean returnActivationRule) {
final QuotaTariffResponse response = new QuotaTariffResponse();
Expand Down Expand Up @@ -501,15 +496,14 @@ public QuotaTariffVO updateQuotaTariffPlan(QuotaTariffUpdateCmd cmd) {
Integer position = cmd.getPosition();

warnQuotaTariffUpdateDeprecatedFields(cmd);
jsInterpreterHelper.ensureInterpreterEnabledIfParameterProvided(ApiConstants.ACTIVATION_RULE, StringUtils.isNotBlank(activationRule));

QuotaTariffVO currentQuotaTariff = _quotaTariffDao.findByName(name);

if (currentQuotaTariff == null) {
throw new InvalidParameterValueException(String.format("There is no quota tariffs with name [%s].", name));
}

checkActivationRulesAllowed(activationRule);

Date currentQuotaTariffStartDate = currentQuotaTariff.getEffectiveOn();

currentQuotaTariff.setRemoved(now);
Expand Down Expand Up @@ -758,14 +752,14 @@ public QuotaTariffVO createQuotaTariff(QuotaTariffCreateCmd cmd) {
String activationRule = cmd.getActivationRule();
Integer position = ObjectUtils.defaultIfNull(cmd.getPosition(), 1);

jsInterpreterHelper.ensureInterpreterEnabledIfParameterProvided(ApiConstants.ACTIVATION_RULE, StringUtils.isNotBlank(activationRule));

QuotaTariffVO currentQuotaTariff = _quotaTariffDao.findByName(name);

if (currentQuotaTariff != null) {
throw new InvalidParameterValueException(String.format("A quota tariff with name [%s] already exist.", name));
}

checkActivationRulesAllowed(activationRule);

if (startDate.compareTo(now) < 0) {
throw new InvalidParameterValueException(String.format("The value passed as Quota tariff's start date is in the past: [%s]. " +
"Please, inform a date in the future or do not pass the parameter to use the current date and time.", startDate));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,4 @@ public interface QuotaService extends PluggableService {

boolean saveQuotaAccount(AccountVO account, BigDecimal aggrUsage, Date endDate);

boolean isJsInterpretationEnabled();

}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.server.ManagementService;
import com.cloud.user.Account;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
Expand Down Expand Up @@ -95,8 +94,6 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi

private TimeZone _usageTimezone;

private boolean jsInterpretationEnabled = false;

public QuotaServiceImpl() {
super();
}
Expand All @@ -108,8 +105,6 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
String timeZoneStr = ObjectUtils.defaultIfNull(_configDao.getValue(Config.UsageAggregationTimezone.toString()), "GMT");
_usageTimezone = TimeZone.getTimeZone(timeZoneStr);

jsInterpretationEnabled = ManagementService.JsInterpretationEnabled.value();

return true;
}

Expand Down Expand Up @@ -298,9 +293,4 @@ public void setMinBalance(Long accountId, Double balance) {
_quotaAcc.updateQuotaAccount(accountId, acc);
}
}

@Override
public boolean isJsInterpretationEnabled() {
return jsInterpretationEnabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
import org.apache.cloudstack.framework.extensions.vo.ExtensionResourceMapVO;
import org.apache.cloudstack.framework.extensions.vo.ExtensionVO;
import org.apache.cloudstack.gpu.GpuService;
import org.apache.cloudstack.jsinterpreter.JsInterpreterHelper;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
Expand Down Expand Up @@ -310,6 +311,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
private GpuService gpuService;
@Inject
ManagementService managementService;
@Inject
JsInterpreterHelper jsInterpreterHelper;

private List<? extends Discoverer> _discoverers;

Expand Down Expand Up @@ -2818,9 +2821,6 @@ private void updateHostTags(HostVO host, Long hostId, List<String> hostTags, Boo

@Override
public Host updateHost(final UpdateHostCmd cmd) throws NoTransitionException {
managementService.checkJsInterpretationAllowedIfNeededForParameterValue(ApiConstants.IS_TAG_A_RULE,
Boolean.TRUE.equals(cmd.getIsTagARule()));

return updateHost(cmd.getId(), cmd.getName(), cmd.getOsCategoryId(),
cmd.getAllocationState(), cmd.getUrl(), cmd.getHostTags(), cmd.getIsTagARule(), cmd.getAnnotation(), false,
cmd.getExternalDetails(), cmd.isCleanupExternalDetails());
Expand All @@ -2830,6 +2830,8 @@ private Host updateHost(Long hostId, String name, Long guestOSCategoryId, String
String url, List<String> hostTags, Boolean isTagARule, String annotation,
boolean isUpdateFromHostHealthCheck, Map<String, String> externalDetails,
boolean cleanupExternalDetails) throws NoTransitionException {
jsInterpreterHelper.ensureInterpreterEnabledIfParameterProvided(ApiConstants.IS_TAG_A_RULE, Boolean.TRUE.equals(isTagARule));

// Verify that the host exists
final HostVO host = _hostDao.findById(hostId);
if (host == null) {
Expand Down
23 changes: 4 additions & 19 deletions server/src/main/java/com/cloud/server/ManagementServerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1082,8 +1082,6 @@ public class ManagementServerImpl extends MutualExclusiveIdsManagerBase implemen

protected List<DeploymentPlanner> _planners;

private boolean jsInterpretationEnabled = false;

private final List<HypervisorType> supportedHypervisors = new ArrayList<>();

public List<DeploymentPlanner> getPlanners() {
Expand Down Expand Up @@ -1164,8 +1162,6 @@ public boolean configure(final String name, final Map<String, Object> params) th
supportedHypervisors.add(HypervisorType.KVM);
supportedHypervisors.add(HypervisorType.XenServer);

jsInterpretationEnabled = JsInterpretationEnabled.value();

return true;
}

Expand Down Expand Up @@ -4374,10 +4370,8 @@ public List<Class<?>> getCommands() {
cmdList.add(ListGuestVlansCmd.class);
cmdList.add(AssignVolumeCmd.class);
cmdList.add(ListSecondaryStorageSelectorsCmd.class);
if (jsInterpretationEnabled) {
cmdList.add(CreateSecondaryStorageSelectorCmd.class);
cmdList.add(UpdateSecondaryStorageSelectorCmd.class);
}
cmdList.add(CreateSecondaryStorageSelectorCmd.class);
cmdList.add(UpdateSecondaryStorageSelectorCmd.class);
cmdList.add(RemoveSecondaryStorageSelectorCmd.class);
cmdList.add(ListAffectedVmsForStorageScopeChangeCmd.class);
cmdList.add(ListGuiThemesCmd.class);
Expand Down Expand Up @@ -4435,8 +4429,7 @@ public String getConfigComponentName() {

@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {exposeCloudStackVersionInApiXmlResponse, exposeCloudStackVersionInApiListCapabilities, vmPasswordLength, sshKeyLength, humanReadableSizes, customCsIdentifier,
JsInterpretationEnabled};
return new ConfigKey<?>[] {exposeCloudStackVersionInApiXmlResponse, exposeCloudStackVersionInApiListCapabilities, vmPasswordLength, sshKeyLength, humanReadableSizes, customCsIdentifier};
}

protected class EventPurgeTask extends ManagedContextRunnable {
Expand Down Expand Up @@ -6002,13 +5995,5 @@ public boolean removeManagementServer(RemoveManagementServerCmd cmd) {
public Answer getExternalVmConsole(VirtualMachine vm, Host host) {
return extensionsManager.getInstanceConsole(vm, host);
}
@Override
public void checkJsInterpretationAllowedIfNeededForParameterValue(String paramName, boolean paramValue) {
if (!paramValue || jsInterpretationEnabled) {
return;
}
throw new InvalidParameterValueException(String.format(
"The parameter %s cannot be set to true as JS interpretation is disabled",
paramName));
}

}
15 changes: 8 additions & 7 deletions server/src/main/java/com/cloud/storage/StorageManagerImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.jsinterpreter.JsInterpreterHelper;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.management.ManagementServerHost;
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
Expand Down Expand Up @@ -417,6 +418,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
StorageManager storageManager;
@Inject
ManagementService managementService;
@Inject
JsInterpreterHelper jsInterpreterHelper;

protected List<StoragePoolDiscoverer> _discoverers;

Expand Down Expand Up @@ -962,6 +965,8 @@ protected void checkNFSMountOptionsForUpdate(Map<String, String> details, Storag

@Override
public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, ResourceUnavailableException {
jsInterpreterHelper.ensureInterpreterEnabledIfParameterProvided(ApiConstants.IS_TAG_A_RULE, Boolean.TRUE.equals(cmd.isTagARule()));

String providerName = cmd.getStorageProviderName();
Map<String,String> uriParams = extractUriParamsAsMap(cmd.getUrl());
boolean isFileScheme = "file".equals(uriParams.get("scheme"));
Expand Down Expand Up @@ -1034,9 +1039,6 @@ public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws Resource
throw new PermissionDeniedException(String.format("Cannot perform this operation, Zone is currently disabled: %s", zone));
}

managementService.checkJsInterpretationAllowedIfNeededForParameterValue(ApiConstants.IS_TAG_A_RULE,
Boolean.TRUE.equals(cmd.isTagARule()));

Map<String, Object> params = new HashMap<>();
params.put("zoneId", zone.getId());
params.put("clusterId", clusterId);
Expand Down Expand Up @@ -1218,11 +1220,9 @@ public StoragePool enablePrimaryStoragePool(Long id) {
@ActionEvent(eventType = EventTypes.EVENT_UPDATE_PRIMARY_STORAGE, eventDescription = "update storage pool")
public PrimaryDataStoreInfo updateStoragePool(UpdateStoragePoolCmd cmd) throws IllegalArgumentException {
// Input validation
Long id = cmd.getId();

managementService.checkJsInterpretationAllowedIfNeededForParameterValue(ApiConstants.IS_TAG_A_RULE,
Boolean.TRUE.equals(cmd.isTagARule()));
jsInterpreterHelper.ensureInterpreterEnabledIfParameterProvided(ApiConstants.IS_TAG_A_RULE, Boolean.TRUE.equals(cmd.isTagARule()));

Long id = cmd.getId();
StoragePoolVO pool = _storagePoolDao.findById(id);
if (pool == null) {
throw new IllegalArgumentException("Unable to find storage pool with ID: " + id);
Expand Down Expand Up @@ -2751,6 +2751,7 @@ protected void validateHeuristicRule(String heuristicRule) {
if (StringUtils.isBlank(heuristicRule)) {
throw new IllegalArgumentException("Unable to create a new secondary storage selector as the given heuristic rule is blank.");
}
jsInterpreterHelper.ensureInterpreterEnabledIfParameterProvided(ApiConstants.HEURISTIC_RULE, true);
}

public void syncDatastoreClusterStoragePool(long datastoreClusterPoolId, List<ModifyStoragePoolAnswer> childDatastoreAnswerList, long hostId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@

package org.apache.cloudstack.jsinterpreter;

import com.cloud.exception.InvalidParameterValueException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.cloudstack.utils.jsinterpreter.JsInterpreter;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
Expand All @@ -36,9 +40,13 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsInterpreterHelper {
public class JsInterpreterHelper implements Configurable {
private final Logger logger = LogManager.getLogger(getClass());

public static final ConfigKey<Boolean> JS_INTERPRETATION_ENABLED = new ConfigKey<>(ConfigKey.CATEGORY_SYSTEM, Boolean.class, "js.interpretation.enabled",
"false", "Enable/disable all JavaScript interpretation related functionalities.",
true, ConfigKey.Scope.Global);

private static final String NAME = "name";
private static final String PROPERTY = "property";
private static final String TYPE = "type";
Expand Down Expand Up @@ -237,4 +245,21 @@ public Set<String> getVariables() {
public void setVariables(Set<String> variables) {
this.variables = variables;
}

public void ensureInterpreterEnabledIfParameterProvided(String paramName, boolean paramProvided) {
if (paramProvided && !JS_INTERPRETATION_ENABLED.value()) {
throw new InvalidParameterValueException(String.format(
"'%s' cannot be set because JavaScript interpretation is disabled in setting '%s'.", paramName, JS_INTERPRETATION_ENABLED.key()));
}
}

@Override
public String getConfigComponentName() {
return JsInterpreter.class.getSimpleName();
}

@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] { JS_INTERPRETATION_ENABLED };
}
}