Skip to content

Commit b75d8a7

Browse files
authored
Merge branch '4.20' into fix-ssvm-migrate-stgNet
2 parents edbda62 + 3dc2305 commit b75d8a7

166 files changed

Lines changed: 3619 additions & 682 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/linters/codespell.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ environmnet
188188
equivalant
189189
erro
190190
erronous
191+
errorprone
191192
everthing
192193
everytime
193194
excetion

agent/src/main/java/com/cloud/agent/mockvm/MockVmMgr.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ public void freeVncPort(int port) {
249249
public MockVm createVmFromSpec(VirtualMachineTO vmSpec) {
250250
String vmName = vmSpec.getName();
251251
long ramSize = vmSpec.getMinRam();
252-
int utilizationPercent = randSeed.nextInt() % 100;
252+
int utilizationPercent = randSeed.nextInt(100);
253253
MockVm vm = null;
254254

255255
synchronized (this) {

api/src/main/java/org/apache/cloudstack/api/ApiArgValidator.java

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,18 @@
1717

1818
package org.apache.cloudstack.api;
1919

20+
import java.util.Locale;
21+
import java.util.regex.Pattern;
22+
23+
import org.apache.commons.lang3.StringUtils;
24+
25+
import com.cloud.exception.InvalidParameterValueException;
26+
import com.cloud.utils.UuidUtils;
27+
2028
public enum ApiArgValidator {
2129
/**
22-
* Validates if the parameter is null or empty with the method {@link Strings#isNullOrEmpty(String)}.
30+
* Validates if the parameter is null or empty with the method {@link StringUtils#isEmpty(CharSequence)}.
31+
* Validation is currently done in the method ParamProcessWorker#validateNonEmptyString(String, String).
2332
*/
2433
NotNullOrEmpty,
2534

@@ -29,12 +38,72 @@ public enum ApiArgValidator {
2938
PositiveNumber,
3039

3140
/**
32-
* Validates if the parameter is an UUID with the method {@link UuidUtils#isUuid(String)}.
41+
* Validates if the parameter is a UUID with the method {@link UuidUtils#isUuid(String)}.
42+
* Validation is currently done in the method ParamProcessWorker#validateUuidString(String, String).
3343
*/
3444
UuidString,
3545

3646
/**
3747
* Validates if the parameter is a valid RFC Compliance domain name.
3848
*/
3949
RFCComplianceDomainName,
50+
51+
/**
52+
* Validates command option strings to avoid unsafe/code-like content.
53+
*/
54+
SafeCommandOptions((param, annotation) -> {
55+
if (BaseCmd.CommandType.STRING.equals(annotation.type())) {
56+
validateSafeCommandOptions(param, annotation.name());
57+
}
58+
});
59+
60+
private static final Pattern SAFE_COMMAND_OPTIONS_PATTERN = Pattern.compile("^[A-Za-z0-9,._=:/+\\-\\s]*$");
61+
62+
private static final String[] UNSAFE_TOKENS = {
63+
"$(", "`", "&&", "||", ";", "|", ">", "<"
64+
};
65+
66+
private final ValidationRule rule;
67+
68+
ApiArgValidator() {
69+
this(null);
70+
}
71+
72+
ApiArgValidator(ValidationRule rule) {
73+
this.rule = rule;
74+
}
75+
76+
public void validate(final Object paramObj, final Parameter annotation) {
77+
if (rule != null) {
78+
rule.validate(paramObj, annotation);
79+
}
80+
}
81+
82+
private static void validateSafeCommandOptions(final Object param, final String argName) {
83+
final String value = String.valueOf(param);
84+
if (StringUtils.isBlank(value)) {
85+
return;
86+
}
87+
88+
if (!SAFE_COMMAND_OPTIONS_PATTERN.matcher(value).matches()) {
89+
throwInvalidParameterValueException(argName, "contains unsupported or unsafe characters");
90+
}
91+
92+
final String normalized = value.toLowerCase(Locale.ROOT);
93+
for (String token : UNSAFE_TOKENS) {
94+
if (normalized.contains(token)) {
95+
throwInvalidParameterValueException(argName, "contains code-like or unsafe content");
96+
}
97+
}
98+
}
99+
100+
private static void throwInvalidParameterValueException(final String argName, final String customMsg) {
101+
throw new InvalidParameterValueException(String.format("Invalid value provided for API arg: %s%s", argName,
102+
StringUtils.isBlank(customMsg) ? "" : " - " + customMsg));
103+
}
104+
105+
@FunctionalInterface
106+
interface ValidationRule {
107+
void validate(Object paramObj, Parameter annotation);
108+
}
40109
}

api/src/main/java/org/apache/cloudstack/api/command/admin/backup/UpdateBackupOfferingCmd.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ public Boolean getAllowUserDrivenBackups() {
8383
public void execute() {
8484
try {
8585
if (StringUtils.isAllEmpty(getName(), getDescription()) && getAllowUserDrivenBackups() == null) {
86-
throw new InvalidParameterValueException(String.format("Can't update Backup Offering [id: %s] because there are no parameters to be updated, at least one of the",
87-
"following should be informed: name, description or allowUserDrivenBackups.", id));
86+
throw new InvalidParameterValueException(String.format("Can't update Backup Offering [id: %s] because there are no parameters to be updated," +
87+
" at least one of the following should be passed: name, description or allowUserDrivenBackups.", id));
8888
}
8989

9090
BackupOffering result = backupManager.updateBackupOffering(this);

api/src/main/java/org/apache/cloudstack/api/command/admin/vm/ResetVMPasswordCmdByAdmin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@
2727
@APICommand(name = "resetPasswordForVirtualMachine", responseObject=UserVmResponse.class, description = "Resets the password for Instance. " +
2828
"The Instance must be in a \"Stopped\" state and the Template must already " +
2929
"support this feature for this command to take effect. [async]", responseView = ResponseView.Full, entityType = {VirtualMachine.class},
30-
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true)
30+
requestHasSensitiveInfo = true, responseHasSensitiveInfo = true)
3131
public class ResetVMPasswordCmdByAdmin extends ResetVMPasswordCmd implements AdminCmd {}

api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.commons.collections.MapUtils;
2323

2424
import org.apache.cloudstack.acl.RoleType;
25+
import org.apache.cloudstack.api.ACL;
2526
import org.apache.cloudstack.api.APICommand;
2627
import org.apache.cloudstack.api.ApiCommandResourceType;
2728
import org.apache.cloudstack.api.ApiConstants;
@@ -106,6 +107,7 @@ public class CreateAutoScaleVmProfileCmd extends BaseAsyncCreateCmd {
106107
since = "4.18.0")
107108
private String userData;
108109

110+
@ACL
109111
@Parameter(name = ApiConstants.USER_DATA_ID, type = CommandType.UUID, entityType = UserDataResponse.class, description = "the ID of the Userdata", since = "4.18.1")
110112
private Long userDataId;
111113

api/src/main/java/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ public class UpdateAutoScaleVmProfileCmd extends BaseAsyncCustomIdCmd {
101101
since = "4.18.0")
102102
private String userData;
103103

104+
@ACL
104105
@Parameter(name = ApiConstants.USER_DATA_ID, type = CommandType.UUID, entityType = UserDataResponse.class, description = "the ID of the userdata",
105106
since = "4.18.1")
106107
private Long userDataId;

api/src/main/java/org/apache/cloudstack/api/command/user/backup/repository/AddBackupRepositoryCmd.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import org.apache.cloudstack.acl.RoleType;
2121
import org.apache.cloudstack.api.APICommand;
22+
import org.apache.cloudstack.api.ApiArgValidator;
2223
import org.apache.cloudstack.api.ApiConstants;
2324
import org.apache.cloudstack.api.ApiErrorCode;
2425
import org.apache.cloudstack.api.BaseCmd;
@@ -56,7 +57,8 @@ public class AddBackupRepositoryCmd extends BaseCmd {
5657
@Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, description = "backup repository provider")
5758
private String provider;
5859

59-
@Parameter(name = ApiConstants.MOUNT_OPTIONS, type = CommandType.STRING, description = "shared storage mount options")
60+
@Parameter(name = ApiConstants.MOUNT_OPTIONS, type = CommandType.STRING, description = "shared storage mount options",
61+
validations = {ApiArgValidator.SafeCommandOptions})
6062
private String mountOptions;
6163

6264
@Parameter(name = ApiConstants.ZONE_ID,

api/src/main/java/org/apache/cloudstack/api/command/user/userdata/DeleteUserDataCmd.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package org.apache.cloudstack.api.command.user.userdata;
1818

1919
import org.apache.cloudstack.acl.RoleType;
20+
import org.apache.cloudstack.acl.SecurityChecker;
21+
import org.apache.cloudstack.api.ACL;
2022
import org.apache.cloudstack.api.APICommand;
2123
import org.apache.cloudstack.api.ApiConstants;
2224
import org.apache.cloudstack.api.ApiErrorCode;
@@ -27,7 +29,6 @@
2729
import org.apache.cloudstack.api.response.ProjectResponse;
2830
import org.apache.cloudstack.api.response.SuccessResponse;
2931
import org.apache.cloudstack.api.response.UserDataResponse;
30-
import org.apache.cloudstack.context.CallContext;
3132

3233
import com.cloud.user.Account;
3334
import com.cloud.user.UserData;
@@ -43,6 +44,7 @@ public class DeleteUserDataCmd extends BaseCmd {
4344
//////////////// API parameters /////////////////////
4445
/////////////////////////////////////////////////////
4546

47+
@ACL(accessType = SecurityChecker.AccessType.OperateEntry)
4648
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, required = true, entityType = UserDataResponse.class, description = "The ID of the Userdata")
4749
private Long id;
4850

@@ -97,18 +99,13 @@ public void execute() {
9799

98100
@Override
99101
public long getEntityOwnerId() {
100-
Account account = CallContext.current().getCallingAccount();
101-
if ((account == null || _accountService.isAdmin(account.getId())) && (domainId != null && accountName != null)) {
102-
Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId);
103-
if (userAccount != null) {
104-
return userAccount.getId();
102+
if (id != null) {
103+
UserData userData = _entityMgr.findById(UserData.class, id);
104+
if (userData != null) {
105+
return userData.getAccountId();
105106
}
106107
}
107108

108-
if (account != null) {
109-
return account.getId();
110-
}
111-
112109
return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked
113110
}
114111
}

api/src/main/java/org/apache/cloudstack/api/command/user/userdata/LinkUserDataToTemplateCmd.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package org.apache.cloudstack.api.command.user.userdata;
1919

2020
import org.apache.cloudstack.acl.RoleType;
21+
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
22+
import org.apache.cloudstack.api.ACL;
2123
import org.apache.cloudstack.api.APICommand;
2224
import org.apache.cloudstack.api.ApiConstants;
2325
import org.apache.cloudstack.api.ApiErrorCode;
@@ -56,6 +58,7 @@ public class LinkUserDataToTemplateCmd extends BaseCmd implements AdminCmd {
5658
description = "The ID of the ISO for the Instance")
5759
private Long isoId;
5860

61+
@ACL(accessType = AccessType.OperateEntry)
5962
@Parameter(name = ApiConstants.USER_DATA_ID,
6063
type = CommandType.UUID,
6164
entityType = UserDataResponse.class,

0 commit comments

Comments
 (0)