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 <abhishek.mrt22@gmail.com>
1 parent c8d44d9 commit 03a4b9f

12 files changed

Lines changed: 252 additions & 107 deletions

File tree

‎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
importjava.util.List;
2121
importjava.util.Map;
2222

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

7070
importcom.cloud.alert.Alert;
7171
importcom.cloud.capacity.Capacity;
@@ -85,6 +85,7 @@
8585
importcom.cloud.storage.GuestOsCategory;
8686
importcom.cloud.storage.StoragePool;
8787
importcom.cloud.user.SSHKeyPair;
88+
importcom.cloud.user.UserData;
8889
importcom.cloud.utils.Pair;
8990
importcom.cloud.utils.Ternary;
9091
importcom.cloud.vm.InstanceGroup;
@@ -98,6 +99,14 @@
9899
publicinterfaceManagementService {
99100
staticfinalStringName = "management-server";
100101

102+
ConfigKey<Boolean> JsInterpretationEnabled = newConfigKey<>("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(PatchSystemVMCmdcmd);
483492

493+
voidcheckJsInterpretationAllowedIfNeededForParameterValue(StringparamName, booleanparamValue);
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
importjavax.inject.Inject;
3333
importjavax.naming.ConfigurationException;
3434

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

6362
importcom.cloud.usage.UsageVO;
6463
importcom.cloud.usage.dao.UsageDao;
64+
importcom.cloud.user.Account;
6565
importcom.cloud.user.AccountVO;
6666
importcom.cloud.user.dao.AccountDao;
6767
importcom.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
importjavax.inject.Inject;
4141

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

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

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

143+
protectedvoidcheckActivationRulesAllowed(StringactivationRule) {
144+
if (!_quotaService.isJsInterpretationEnabled() && StringUtils.isNotEmpty(activationRule)) {
145+
thrownewPermissionDeniedException("Quota Tariff Activation Rule cannot be set, as Javascript interpretation is disabled in the configuration.");
146+
}
147+
}
148+
142149
@Override
143150
publicQuotaTariffResponsecreateQuotaTariffResponse(QuotaTariffVOtariff, booleanreturnActivationRule) {
144151
finalQuotaTariffResponseresponse = newQuotaTariffResponse();
@@ -440,6 +447,8 @@ public QuotaTariffVO updateQuotaTariffPlan(QuotaTariffUpdateCmd cmd) {
440447
thrownewInvalidParameterValueException(String.format("There is no quota tariffs with name [%s].", name));
441448
}
442449

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

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

708+
checkActivationRulesAllowed(activationRule);
709+
699710
if (startDate.compareTo(now) < 0) {
700711
thrownewInvalidParameterValueException(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
packageorg.apache.cloudstack.quota;
1818

19-
importcom.cloud.user.AccountVO;
20-
importcom.cloud.utils.component.PluggableService;
19+
importjava.math.BigDecimal;
20+
importjava.util.Date;
21+
importjava.util.List;
2122

2223
importorg.apache.cloudstack.quota.vo.QuotaBalanceVO;
2324
importorg.apache.cloudstack.quota.vo.QuotaUsageVO;
2425

25-
importjava.math.BigDecimal;
26-
importjava.util.Date;
27-
importjava.util.List;
26+
importcom.cloud.user.AccountVO;
27+
importcom.cloud.utils.component.PluggableService;
2828

2929
publicinterfaceQuotaServiceextendsPluggableService {
3030

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

4141
booleansaveQuotaAccount(AccountVOaccount, BigDecimalaggrUsage, DateendDate);
4242

43+
booleanisJsInterpretationEnabled();
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
importcom.cloud.domain.dao.DomainDao;
6161
importcom.cloud.exception.InvalidParameterValueException;
6262
importcom.cloud.exception.PermissionDeniedException;
63+
importcom.cloud.server.ManagementService;
6364
importcom.cloud.user.Account;
6465
importcom.cloud.user.AccountVO;
6566
importcom.cloud.user.dao.AccountDao;
@@ -86,6 +87,8 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
8687

8788
privateTimeZone_usageTimezone;
8889

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

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

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

292+
@Override
293+
publicbooleanisJsInterpretationEnabled() {
294+
returnjsInterpretationEnabled;
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
importcom.cloud.org.Grouping;
155155
importcom.cloud.org.Managed;
156156
importcom.cloud.serializer.GsonHelper;
157+
importcom.cloud.server.ManagementService;
157158
importcom.cloud.service.ServiceOfferingVO;
158159
importcom.cloud.service.dao.ServiceOfferingDao;
159160
importcom.cloud.service.dao.ServiceOfferingDetailsDao;
@@ -271,6 +272,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
271272
privateServiceOfferingDetailsDao_serviceOfferingDetailsDao;
272273
@Inject
273274
privateUserVmManageruserVmManager;
275+
@Inject
276+
ManagementServicemanagementService;
274277

275278
privateList<? extendsDiscoverer> _discoverers;
276279

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

19371940
@Override
19381941
publicHostupdateHost(finalUpdateHostCmdcmd) throwsNoTransitionException {
1942+
managementService.checkJsInterpretationAllowedIfNeededForParameterValue(ApiConstants.IS_TAG_A_RULE,
1943+
Boolean.TRUE.equals(cmd.getIsTagARule()));
1944+
19391945
returnupdateHost(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
protectedList<DeploymentPlanner> _planners;
10421042

1043+
privatebooleanjsInterpretationEnabled = false;
1044+
10431045
privatefinalList<HypervisorType> supportedHypervisors = newArrayList<>();
10441046

10451047
publicList<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
returntrue;
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
publicConfigKey<?>[] getConfigKeys() {
4069-
returnnewConfigKey<?>[] {vmPasswordLength, sshKeyLength, humanReadableSizes, customCsIdentifier};
4075+
returnnewConfigKey<?>[] {vmPasswordLength, sshKeyLength, humanReadableSizes, customCsIdentifier,
4076+
JsInterpretationEnabled};
40704077
}
40714078

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

5533+
@Override
5534+
publicvoidcheckJsInterpretationAllowedIfNeededForParameterValue(StringparamName, booleanparamValue) {
5535+
if (!paramValue || jsInterpretationEnabled) {
5536+
return;
5537+
}
5538+
thrownewInvalidParameterValueException(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
importcom.cloud.resource.ResourceState;
214214
importcom.cloud.server.ConfigurationServer;
215215
importcom.cloud.server.ManagementServer;
216+
importcom.cloud.server.ManagementService;
216217
importcom.cloud.server.StatsCollector;
217218
importcom.cloud.service.dao.ServiceOfferingDetailsDao;
218219
importcom.cloud.storage.Storage.ImageFormat;
@@ -398,6 +399,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
398399
ConfigurationDaoconfigurationDao;
399400
@Inject
400401
privateImageStoreDetailsUtilimageStoreDetailsUtil;
402+
@Inject
403+
ManagementServicemanagementService;
401404

402405
protectedList<StoragePoolDiscoverer> _discoverers;
403406

@@ -1015,6 +1018,9 @@ public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws Resource
10151018
thrownewPermissionDeniedException(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 = newHashMap<>();
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
Longid = cmd.getId();
11991205

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

0 commit comments

Comments
 (0)