diff --git a/api/src/org/apache/cloudstack/api/Parameter.java b/api/src/org/apache/cloudstack/api/Parameter.java index fa6075dc970..e354fda02d5 100644 --- a/api/src/org/apache/cloudstack/api/Parameter.java +++ b/api/src/org/apache/cloudstack/api/Parameter.java @@ -51,4 +51,6 @@ public @interface Parameter { RoleType[] authorized() default {}; ApiArgValidator[] validations() default {}; + + boolean acceptedOnAdminPort() default true; } diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java index f21e2640ba2..e6ac36719e3 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java @@ -18,8 +18,6 @@ package org.apache.cloudstack.api.command.admin.user; import javax.inject.Inject; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -29,6 +27,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.region.RegionService; +import org.apache.log4j.Logger; import com.cloud.user.Account; import com.cloud.user.User; @@ -61,10 +60,12 @@ public class UpdateUserCmd extends BaseCmd { private String lastname; @Parameter(name = ApiConstants.PASSWORD, - type = CommandType.STRING, - description = "Clear text password (default hashed to SHA256SALT). If you wish to use any other hasing algorithm, you would need to write a custom authentication adapter") + type = CommandType.STRING, + description = "Clear text password (default hashed to SHA256SALT). If you wish to use any other hasing algorithm, you would need to write a custom authentication adapter. Can't be passed when command is executed via integration.api.port", + acceptedOnAdminPort = false) private String password; + @Parameter(name = ApiConstants.SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userSecretKey") private String secretKey; diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 6413716b32e..40c95a06ea7 100644 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -44,6 +44,7 @@ import com.cloud.utils.ConstantTimeComparator; import com.cloud.utils.HttpUtils; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +import com.cloud.utils.ReflectUtil; import com.cloud.utils.StringUtils; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ManagerBase; @@ -65,6 +66,7 @@ import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -152,6 +154,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InterruptedIOException; import java.lang.reflect.Type; +import java.lang.reflect.Field; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; @@ -428,8 +431,27 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer if (!(responseType.equals(HttpUtils.RESPONSE_TYPE_JSON) || responseType.equals(HttpUtils.RESPONSE_TYPE_XML))) { responseType = HttpUtils.RESPONSE_TYPE_XML; } - try { + //verify that parameter is legit for passing via admin port + String[] command = (String[]) parameterMap.get("command"); + if (command != null) { + Class cmdClass = getCmdClass(command[0]); + if (cmdClass != null) { + List fields = ReflectUtil.getAllFieldsForClass(cmdClass, BaseCmd.class); + for (Field field : fields) { + Parameter parameterAnnotation = field.getAnnotation(Parameter.class); + if ((parameterAnnotation == null) || !parameterAnnotation.expose()) { + continue; + } + Object paramObj = parameterMap.get(parameterAnnotation.name()); + if (paramObj != null) { + if (!parameterAnnotation.acceptedOnAdminPort()) { + throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, "Parameter " + parameterAnnotation.name() + " can't be passed through the API integration port"); + } + } + } + } + } // always trust commands from API port, user context will always be UID_SYSTEM/ACCOUNT_ID_SYSTEM CallContext.register(accountMgr.getSystemUser(), accountMgr.getSystemAccount()); sb.insert(0, "(userId=" + User.UID_SYSTEM + " accountId=" + Account.ACCOUNT_ID_SYSTEM + " sessionId=" + null + ") ");