Changes error message when using invalid endpoint.url (#8603)

Co-authored-by: lucas.martins.scclouds <lucas.martins@scclouds.com.br>
Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com>
Co-authored-by: erikbocks <erik.bock@outlook.com>
This commit is contained in:
Lucas Martins 2025-12-08 05:41:56 -03:00 committed by GitHub
parent a0ba2aaf3f
commit 12f4321952
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 122 additions and 22 deletions

View File

@ -16,10 +16,15 @@
// under the License.
package org.apache.cloudstack.config;
import com.cloud.exception.InvalidParameterValueException;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ApiServiceConfiguration implements Configurable {
protected static Logger LOGGER = LogManager.getLogger(ApiServiceConfiguration.class);
public static final ConfigKey<String> ManagementServerAddresses = new ConfigKey<>(String.class, "host", "Advanced", "localhost", "The ip address of management server. This can also accept comma separated addresses.", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
public static final ConfigKey<String> ApiServletPath = new ConfigKey<String>("Advanced", String.class, "endpoint.url", "http://localhost:8080/client/api",
"API end point. Can be used by CS components/services deployed remotely, for sending CS API requests", true);
@ -29,6 +34,20 @@ public class ApiServiceConfiguration implements Configurable {
"true", "Are the source checks on API calls enabled (true) or not (false)? See api.allowed.source.cidr.list", true, ConfigKey.Scope.Global);
public static final ConfigKey<String> ApiAllowedSourceCidrList = new ConfigKey<>(String.class, "api.allowed.source.cidr.list", "Advanced",
"0.0.0.0/0,::/0", "Comma separated list of IPv4/IPv6 CIDRs from which API calls can be performed. Can be set on Global and Account levels.", true, ConfigKey.Scope.Account, null, null, null, null, null, ConfigKey.Kind.CSV, null);
public static void validateEndpointUrl() {
String csUrl = getApiServletPathValue();
if (StringUtils.isBlank(csUrl) || StringUtils.containsAny(csUrl, "localhost", "127.0.0.1", "[::1]")) {
LOGGER.error("Global setting [{}] cannot contain localhost or be blank. Current value: {}", ApiServletPath.key(), csUrl);
throw new InvalidParameterValueException("Unable to complete this operation. Contact your cloud admin.");
}
}
public static String getApiServletPathValue() {
return ApiServletPath.value();
}
@Override
public String getConfigComponentName() {
return ApiServiceConfiguration.class.getSimpleName();

View File

@ -0,0 +1,95 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.config;
import com.cloud.exception.InvalidParameterValueException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ApiServiceConfigurationTest {
private static final String LOCALHOST = "http://localhost";
private static final String ENDPOINT_URL = "https://acs.clouds.com/client/api";
private static final String WHITE_SPACE = " ";
private static final String BLANK_STRING = "";
private static final String NULL_STRING = null;
private static final String LOCALHOST_IP = "127.0.0.1";
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlContainLocalhostShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(LOCALHOST);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test
public void validateEndpointUrlTestIfEndpointUrlContainLocalhostShouldNotThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(ENDPOINT_URL);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlIsNullShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(NULL_STRING);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlIsBlankShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(BLANK_STRING);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlIsWhiteSpaceShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(WHITE_SPACE);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
@Test(expected = InvalidParameterValueException.class)
public void validateEndpointUrlTestIfEndpointUrlContainLocalhostIpShouldThrowInvalidParameterValueException() {
try (MockedStatic<ApiServiceConfiguration> apiServiceConfigurationMockedStatic = Mockito.mockStatic(ApiServiceConfiguration.class)) {
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::getApiServletPathValue).thenReturn(LOCALHOST_IP);
apiServiceConfigurationMockedStatic.when(ApiServiceConfiguration::validateEndpointUrl).thenCallRealMethod();
ApiServiceConfiguration.validateEndpointUrl();
}
}
}

View File

@ -905,15 +905,6 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
return response;
}
private void validateEndpointUrl() {
String csUrl = ApiServiceConfiguration.ApiServletPath.value();
if (csUrl == null || csUrl.contains("localhost")) {
String error = String.format("Global setting %s has to be set to the Management Server's API end point",
ApiServiceConfiguration.ApiServletPath.key());
throw new InvalidParameterValueException(error);
}
}
private DataCenter validateAndGetZoneForKubernetesCreateParameters(Long zoneId, Long networkId) {
DataCenter zone = dataCenterDao.findById(zoneId);
if (zone == null) {
@ -1008,7 +999,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
}
private void validateManagedKubernetesClusterCreateParameters(final CreateKubernetesClusterCmd cmd) throws CloudRuntimeException {
validateEndpointUrl();
ApiServiceConfiguration.validateEndpointUrl();
final String name = cmd.getName();
final Long zoneId = cmd.getZoneId();
final Long kubernetesVersionId = cmd.getKubernetesVersionId();
@ -1308,7 +1299,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
KubernetesVersionManagerImpl.MINIMUN_AUTOSCALER_SUPPORTED_VERSION ));
}
validateEndpointUrl();
ApiServiceConfiguration.validateEndpointUrl();
if (minSize == null || maxSize == null) {
throw new InvalidParameterValueException("Autoscaling requires minsize and maxsize to be passed");
@ -1413,7 +1404,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
private void validateKubernetesClusterUpgradeParameters(UpgradeKubernetesClusterCmd cmd) {
// Validate parameters
validateEndpointUrl();
ApiServiceConfiguration.validateEndpointUrl();
final Long kubernetesClusterId = cmd.getId();
final Long upgradeVersionId = cmd.getKubernetesVersionId();

View File

@ -685,7 +685,7 @@ public class KubernetesClusterActionWorker {
try {
String command = String.format("sudo %s/%s -u '%s' -k '%s' -s '%s'",
scriptPath, deploySecretsScriptFilename, ApiServiceConfiguration.ApiServletPath.value(), keys[0], keys[1]);
scriptPath, deploySecretsScriptFilename, ApiServiceConfiguration.getApiServletPathValue(), keys[0], keys[1]);
Account account = accountDao.findById(kubernetesCluster.getAccountId());
if (account != null && account.getType() == Account.Type.PROJECT) {
String projectId = projectService.findByProjectAccountId(account.getId()).getUuid();

View File

@ -512,7 +512,6 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage
String apiKey = user.getApiKey();
String secretKey = user.getSecretKey();
String csUrl = ApiServiceConfiguration.ApiServletPath.value();
if (apiKey == null) {
throw new InvalidParameterValueException("apiKey for user: " + user.getUsername() + " is empty. Please generate it");
@ -522,9 +521,7 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage
throw new InvalidParameterValueException("secretKey for user: " + user.getUsername() + " is empty. Please generate it");
}
if (csUrl == null || csUrl.contains("localhost")) {
throw new InvalidParameterValueException(String.format("Global setting %s has to be set to the Management Server's API end point", ApiServiceConfiguration.ApiServletPath.key()));
}
ApiServiceConfiguration.validateEndpointUrl();
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_AUTOSCALEVMPROFILE_CREATE, eventDescription = "creating autoscale vm profile", create = true)

View File

@ -337,7 +337,6 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
String apiKey = null;
String secretKey = null;
String csUrl = ApiServiceConfiguration.ApiServletPath.value();
Network.Provider provider = getLoadBalancerServiceProvider(lb);
if (Network.Provider.Netscaler.equals(provider)) {
Long autoscaleUserId = autoScaleVmProfile.getAutoScaleUserId();
@ -358,13 +357,12 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
throw new InvalidParameterValueException("secretKey for user: " + user.getUsername() + " is empty. Please generate it");
}
if (csUrl == null || csUrl.contains("localhost")) {
throw new InvalidParameterValueException(String.format("Global setting %s has to be set to the Management Server's API end point", ApiServiceConfiguration.ApiServletPath.key()));
}
ApiServiceConfiguration.validateEndpointUrl();
}
LbAutoScaleVmProfile lbAutoScaleVmProfile =
new LbAutoScaleVmProfile(autoScaleVmProfile, apiKey, secretKey, csUrl, zoneId, domainId, serviceOfferingId, templateId, vmName, lbNetworkUuid);
new LbAutoScaleVmProfile(autoScaleVmProfile, apiKey, secretKey, ApiServiceConfiguration.getApiServletPathValue(), zoneId, domainId, serviceOfferingId, templateId,
vmName, lbNetworkUuid);
return new LbAutoScaleVmGroup(vmGroup, autoScalePolicies, lbAutoScaleVmProfile, currentState);
}