Skip to content

Commit 03a4b9f

Browse files
shwstpprweizhouapache
authored andcommitted
server,utils: improve js interpretation functionality
Make JS interpretation functionalities configurable via a hidden config - js.interpretation.enabled Default value is false, making such functionalities disabled, ie, new heuristic rules cannot be added or updated. For JsInterpretor, use --no-java --no-syntax-extensions args and a deny-all ClassFilter. Replace string-spliced vars with ENGINE_SCOPE Bindings, use a fresh ScriptContext per run, and compile before eval. Use a named daemon worker with hard timeouts and capture stdout. Signed-off-by: Abhishek Kumar <[email protected]>
1 parent c8d44d9 commit 03a4b9f

File tree

12 files changed

+252
-107
lines changed

12 files changed

+252
-107
lines changed

api/src/main/java/com/cloud/server/ManagementService.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.util.List;
2121
import java.util.Map;
2222

23-
import com.cloud.user.UserData;
2423
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
2524
import org.apache.cloudstack.api.command.admin.config.ListCfgGroupsByCmd;
2625
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
@@ -66,6 +65,7 @@
6665
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
6766
import org.apache.cloudstack.config.Configuration;
6867
import org.apache.cloudstack.config.ConfigurationGroup;
68+
import org.apache.cloudstack.framework.config.ConfigKey;
6969

7070
import com.cloud.alert.Alert;
7171
import com.cloud.capacity.Capacity;
@@ -85,6 +85,7 @@
8585
import com.cloud.storage.GuestOsCategory;
8686
import com.cloud.storage.StoragePool;
8787
import com.cloud.user.SSHKeyPair;
88+
import com.cloud.user.UserData;
8889
import com.cloud.utils.Pair;
8990
import com.cloud.utils.Ternary;
9091
import com.cloud.vm.InstanceGroup;
@@ -98,6 +99,14 @@
9899
public interface ManagementService {
99100
static final String Name = "management-server";
100101

102+
ConfigKey<Boolean> JsInterpretationEnabled = new ConfigKey<>("Hidden"
103+
, Boolean.class
104+
, "js.interpretation.enabled"
105+
, "false"
106+
, "Enable/Disable all JavaScript interpretation related functionalities to create or update Javascript rules."
107+
, false
108+
, ConfigKey.Scope.Global);
109+
101110
/**
102111
* returns the a map of the names/values in the configuration table
103112
*
@@ -481,4 +490,6 @@ VirtualMachine upgradeSystemVM(ScaleSystemVMCmd cmd) throws ResourceUnavailableE
481490

482491
Pair<Boolean, String> patchSystemVM(PatchSystemVMCmd cmd);
483492

493+
void checkJsInterpretationAllowedIfNeededForParameterValue(String paramName, boolean paramValue);
494+
484495
}

framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaManagerImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import javax.inject.Inject;
3333
import javax.naming.ConfigurationException;
3434

35-
import com.cloud.user.Account;
3635
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
3736
import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
3837
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableHelper;
@@ -62,6 +61,7 @@
6261

6362
import com.cloud.usage.UsageVO;
6463
import com.cloud.usage.dao.UsageDao;
64+
import com.cloud.user.Account;
6565
import com.cloud.user.AccountVO;
6666
import com.cloud.user.dao.AccountDao;
6767
import com.cloud.utils.DateUtil;
@@ -467,7 +467,7 @@ protected void injectPresetVariablesIntoJsInterpreter(JsInterpreter jsInterprete
467467

468468
}
469469

470-
jsInterpreter.injectStringVariable("resourceType", presetVariables.getResourceType());
470+
jsInterpreter.injectVariable("resourceType", presetVariables.getResourceType());
471471
jsInterpreter.injectVariable("value", presetVariables.getValue().toString());
472472
jsInterpreter.injectVariable("zone", presetVariables.getZone().toString());
473473
}

framework/quota/src/test/java/org/apache/cloudstack/quota/QuotaManagerImplTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ public void injectPresetVariablesIntoJsInterpreterTestProjectIsNullDoNotInjectPr
270270
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("account"), Mockito.anyString());
271271
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("domain"), Mockito.anyString());
272272
Mockito.verify(jsInterpreterMock, Mockito.never()).injectVariable(Mockito.eq("project"), Mockito.anyString());
273-
Mockito.verify(jsInterpreterMock).injectStringVariable(Mockito.eq("resourceType"), Mockito.anyString());
273+
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("resourceType"), Mockito.anyString());
274274
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("value"), Mockito.anyString());
275275
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("zone"), Mockito.anyString());
276276
}
@@ -291,7 +291,7 @@ public void injectPresetVariablesIntoJsInterpreterTestProjectIsNotNullInjectProj
291291
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("account"), Mockito.anyString());
292292
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("domain"), Mockito.anyString());
293293
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("project"), Mockito.anyString());
294-
Mockito.verify(jsInterpreterMock).injectStringVariable(Mockito.eq("resourceType"), Mockito.anyString());
294+
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("resourceType"), Mockito.anyString());
295295
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("value"), Mockito.anyString());
296296
Mockito.verify(jsInterpreterMock).injectVariable(Mockito.eq("zone"), Mockito.anyString());
297297
}

plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939

4040
import javax.inject.Inject;
4141

42-
import com.cloud.utils.DateUtil;
4342
import org.apache.cloudstack.api.ApiErrorCode;
4443
import org.apache.cloudstack.api.ServerApiException;
4544
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
@@ -70,35 +69,37 @@
7069
import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDao;
7170
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
7271
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
73-
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
7472
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
73+
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
7574
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
7675
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
7776
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
7877
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
7978
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
8079
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
8180
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
81+
import org.apache.commons.lang3.ObjectUtils;
8282
import org.apache.commons.lang3.StringUtils;
8383
import org.apache.commons.lang3.reflect.FieldUtils;
84-
import org.apache.commons.lang3.ObjectUtils;
85-
import org.apache.logging.log4j.Logger;
8684
import org.apache.logging.log4j.LogManager;
85+
import org.apache.logging.log4j.Logger;
8786
import org.springframework.stereotype.Component;
8887

8988
import com.cloud.domain.DomainVO;
9089
import com.cloud.domain.dao.DomainDao;
90+
import com.cloud.event.ActionEvent;
91+
import com.cloud.event.EventTypes;
9192
import com.cloud.exception.InvalidParameterValueException;
93+
import com.cloud.exception.PermissionDeniedException;
9294
import com.cloud.user.Account;
9395
import com.cloud.user.AccountManager;
9496
import com.cloud.user.AccountVO;
9597
import com.cloud.user.User;
9698
import com.cloud.user.dao.AccountDao;
9799
import com.cloud.user.dao.UserDao;
100+
import com.cloud.utils.DateUtil;
98101
import com.cloud.utils.Pair;
99102
import com.cloud.utils.db.Filter;
100-
import com.cloud.event.ActionEvent;
101-
import com.cloud.event.EventTypes;
102103

103104
@Component
104105
public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
@@ -139,6 +140,12 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
139140
@Inject
140141
private ApiDiscoveryService apiDiscoveryService;
141142

143+
protected void checkActivationRulesAllowed(String activationRule) {
144+
if (!_quotaService.isJsInterpretationEnabled() && StringUtils.isNotEmpty(activationRule)) {
145+
throw new PermissionDeniedException("Quota Tariff Activation Rule cannot be set, as Javascript interpretation is disabled in the configuration.");
146+
}
147+
}
148+
142149
@Override
143150
public QuotaTariffResponse createQuotaTariffResponse(QuotaTariffVO tariff, boolean returnActivationRule) {
144151
final QuotaTariffResponse response = new QuotaTariffResponse();
@@ -440,6 +447,8 @@ public QuotaTariffVO updateQuotaTariffPlan(QuotaTariffUpdateCmd cmd) {
440447
throw new InvalidParameterValueException(String.format("There is no quota tariffs with name [%s].", name));
441448
}
442449

450+
checkActivationRulesAllowed(activationRule);
451+
443452
Date currentQuotaTariffStartDate = currentQuotaTariff.getEffectiveOn();
444453

445454
currentQuotaTariff.setRemoved(now);
@@ -696,6 +705,8 @@ public QuotaTariffVO createQuotaTariff(QuotaTariffCreateCmd cmd) {
696705
throw new InvalidParameterValueException(String.format("A quota tariff with name [%s] already exist.", name));
697706
}
698707

708+
checkActivationRulesAllowed(activationRule);
709+
699710
if (startDate.compareTo(now) < 0) {
700711
throw new InvalidParameterValueException(String.format("The value passed as Quota tariff's start date is in the past: [%s]. " +
701712
"Please, inform a date in the future or do not pass the parameter to use the current date and time.", startDate));

plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaService.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
//under the License.
1717
package org.apache.cloudstack.quota;
1818

19-
import com.cloud.user.AccountVO;
20-
import com.cloud.utils.component.PluggableService;
19+
import java.math.BigDecimal;
20+
import java.util.Date;
21+
import java.util.List;
2122

2223
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
2324
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
2425

25-
import java.math.BigDecimal;
26-
import java.util.Date;
27-
import java.util.List;
26+
import com.cloud.user.AccountVO;
27+
import com.cloud.utils.component.PluggableService;
2828

2929
public interface QuotaService extends PluggableService {
3030

@@ -40,4 +40,6 @@ public interface QuotaService extends PluggableService {
4040

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

43+
boolean isJsInterpretationEnabled();
44+
4345
}

plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import com.cloud.domain.dao.DomainDao;
6161
import com.cloud.exception.InvalidParameterValueException;
6262
import com.cloud.exception.PermissionDeniedException;
63+
import com.cloud.server.ManagementService;
6364
import com.cloud.user.Account;
6465
import com.cloud.user.AccountVO;
6566
import com.cloud.user.dao.AccountDao;
@@ -86,6 +87,8 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
8687

8788
private TimeZone _usageTimezone;
8889

90+
private boolean jsInterpretationEnabled = false;
91+
8992
public QuotaServiceImpl() {
9093
super();
9194
}
@@ -97,6 +100,8 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
97100
String timeZoneStr = ObjectUtils.defaultIfNull(_configDao.getValue(Config.UsageAggregationTimezone.toString()), "GMT");
98101
_usageTimezone = TimeZone.getTimeZone(timeZoneStr);
99102

103+
jsInterpretationEnabled = ManagementService.JsInterpretationEnabled.value();
104+
100105
return true;
101106
}
102107

@@ -284,4 +289,8 @@ public void setMinBalance(Long accountId, Double balance) {
284289
}
285290
}
286291

292+
@Override
293+
public boolean isJsInterpretationEnabled() {
294+
return jsInterpretationEnabled;
295+
}
287296
}

server/src/main/java/com/cloud/resource/ResourceManagerImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
import com.cloud.org.Grouping;
155155
import com.cloud.org.Managed;
156156
import com.cloud.serializer.GsonHelper;
157+
import com.cloud.server.ManagementService;
157158
import com.cloud.service.ServiceOfferingVO;
158159
import com.cloud.service.dao.ServiceOfferingDao;
159160
import com.cloud.service.dao.ServiceOfferingDetailsDao;
@@ -271,6 +272,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
271272
private ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
272273
@Inject
273274
private UserVmManager userVmManager;
275+
@Inject
276+
ManagementService managementService;
274277

275278
private List<? extends Discoverer> _discoverers;
276279

@@ -1936,6 +1939,9 @@ private void updateHostTags(HostVO host, Long hostId, List<String> hostTags, Boo
19361939

19371940
@Override
19381941
public Host updateHost(final UpdateHostCmd cmd) throws NoTransitionException {
1942+
managementService.checkJsInterpretationAllowedIfNeededForParameterValue(ApiConstants.IS_TAG_A_RULE,
1943+
Boolean.TRUE.equals(cmd.getIsTagARule()));
1944+
19391945
return updateHost(cmd.getId(), cmd.getName(), cmd.getOsCategoryId(),
19401946
cmd.getAllocationState(), cmd.getUrl(), cmd.getHostTags(), cmd.getIsTagARule(), cmd.getAnnotation(), false);
19411947
}

server/src/main/java/com/cloud/server/ManagementServerImpl.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
10401040

10411041
protected List<DeploymentPlanner> _planners;
10421042

1043+
private boolean jsInterpretationEnabled = false;
1044+
10431045
private final List<HypervisorType> supportedHypervisors = new ArrayList<>();
10441046

10451047
public List<DeploymentPlanner> getPlanners() {
@@ -1126,6 +1128,8 @@ public boolean configure(final String name, final Map<String, Object> params) th
11261128
supportedHypervisors.add(HypervisorType.KVM);
11271129
supportedHypervisors.add(HypervisorType.XenServer);
11281130

1131+
jsInterpretationEnabled = JsInterpretationEnabled.value();
1132+
11291133
return true;
11301134
}
11311135

@@ -4022,8 +4026,10 @@ public List<Class<?>> getCommands() {
40224026
cmdList.add(ListGuestVlansCmd.class);
40234027
cmdList.add(AssignVolumeCmd.class);
40244028
cmdList.add(ListSecondaryStorageSelectorsCmd.class);
4025-
cmdList.add(CreateSecondaryStorageSelectorCmd.class);
4026-
cmdList.add(UpdateSecondaryStorageSelectorCmd.class);
4029+
if (jsInterpretationEnabled) {
4030+
cmdList.add(CreateSecondaryStorageSelectorCmd.class);
4031+
cmdList.add(UpdateSecondaryStorageSelectorCmd.class);
4032+
}
40274033
cmdList.add(RemoveSecondaryStorageSelectorCmd.class);
40284034
cmdList.add(ListAffectedVmsForStorageScopeChangeCmd.class);
40294035

@@ -4066,7 +4072,8 @@ public String getConfigComponentName() {
40664072

40674073
@Override
40684074
public ConfigKey<?>[] getConfigKeys() {
4069-
return new ConfigKey<?>[] {vmPasswordLength, sshKeyLength, humanReadableSizes, customCsIdentifier};
4075+
return new ConfigKey<?>[] {vmPasswordLength, sshKeyLength, humanReadableSizes, customCsIdentifier,
4076+
JsInterpretationEnabled};
40704077
}
40714078

40724079
protected class EventPurgeTask extends ManagedContextRunnable {
@@ -5523,4 +5530,13 @@ public void setLockControllerListener(final LockControllerListener lockControlle
55235530
_lockControllerListener = lockControllerListener;
55245531
}
55255532

5533+
@Override
5534+
public void checkJsInterpretationAllowedIfNeededForParameterValue(String paramName, boolean paramValue) {
5535+
if (!paramValue || jsInterpretationEnabled) {
5536+
return;
5537+
}
5538+
throw new InvalidParameterValueException(String.format(
5539+
"The parameter %s cannot be set to true as JS interpretation is disabled",
5540+
paramName));
5541+
}
55265542
}

server/src/main/java/com/cloud/storage/StorageManagerImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@
213213
import com.cloud.resource.ResourceState;
214214
import com.cloud.server.ConfigurationServer;
215215
import com.cloud.server.ManagementServer;
216+
import com.cloud.server.ManagementService;
216217
import com.cloud.server.StatsCollector;
217218
import com.cloud.service.dao.ServiceOfferingDetailsDao;
218219
import com.cloud.storage.Storage.ImageFormat;
@@ -398,6 +399,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
398399
ConfigurationDao configurationDao;
399400
@Inject
400401
private ImageStoreDetailsUtil imageStoreDetailsUtil;
402+
@Inject
403+
ManagementService managementService;
401404

402405
protected List<StoragePoolDiscoverer> _discoverers;
403406

@@ -1015,6 +1018,9 @@ public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws Resource
10151018
throw new PermissionDeniedException(String.format("Cannot perform this operation, Zone is currently disabled: %s", zone));
10161019
}
10171020

1021+
managementService.checkJsInterpretationAllowedIfNeededForParameterValue(ApiConstants.IS_TAG_A_RULE,
1022+
Boolean.TRUE.equals(cmd.isTagARule()));
1023+
10181024
Map<String, Object> params = new HashMap<>();
10191025
params.put("zoneId", zone.getId());
10201026
params.put("clusterId", clusterId);
@@ -1197,6 +1203,9 @@ public PrimaryDataStoreInfo updateStoragePool(UpdateStoragePoolCmd cmd) throws I
11971203
// Input validation
11981204
Long id = cmd.getId();
11991205

1206+
managementService.checkJsInterpretationAllowedIfNeededForParameterValue(ApiConstants.IS_TAG_A_RULE,
1207+
Boolean.TRUE.equals(cmd.isTagARule()));
1208+
12001209
StoragePoolVO pool = _storagePoolDao.findById(id);
12011210
if (pool == null) {
12021211
throw new IllegalArgumentException("Unable to find storage pool with ID: " + id);

0 commit comments

Comments
 (0)