Minor console access refactor and improvements (#6919)

This commit is contained in:
Nicolas Vazquez 2022-12-20 05:29:04 -03:00 committed by GitHub
parent 95074f69ba
commit 9ccec161db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 43 deletions

View File

@ -18,14 +18,8 @@ package org.apache.cloudstack.consoleproxy;
import com.cloud.utils.component.Manager; import com.cloud.utils.component.Manager;
import org.apache.cloudstack.api.command.user.consoleproxy.ConsoleEndpoint; import org.apache.cloudstack.api.command.user.consoleproxy.ConsoleEndpoint;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.Configurable;
public interface ConsoleAccessManager extends Manager, Configurable { public interface ConsoleAccessManager extends Manager {
ConfigKey<Boolean> ConsoleProxyExtraSecurityValidationEnabled = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Boolean.class,
"consoleproxy.extra.security.validation.enabled", "false",
"Enable/disable extra security validation for console proxy using an extra token.", true);
ConsoleEndpoint generateConsoleEndpoint(Long vmId, String extraSecurityToken, String clientAddress); ConsoleEndpoint generateConsoleEndpoint(Long vmId, String extraSecurityToken, String clientAddress);

View File

@ -47,10 +47,8 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import org.apache.cloudstack.api.command.user.consoleproxy.ConsoleEndpoint; import org.apache.cloudstack.api.command.user.consoleproxy.ConsoleEndpoint;
import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.security.keys.KeysManager; import org.apache.cloudstack.framework.security.keys.KeysManager;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -60,8 +58,10 @@ import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject; import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -90,6 +90,10 @@ public class ConsoleAccessManagerImpl extends ManagerBase implements ConsoleAcce
public static final Logger s_logger = Logger.getLogger(ConsoleAccessManagerImpl.class.getName()); public static final Logger s_logger = Logger.getLogger(ConsoleAccessManagerImpl.class.getName());
private static final List<VirtualMachine.State> unsupportedConsoleVMState = Arrays.asList(
VirtualMachine.State.Stopped, VirtualMachine.State.Error, VirtualMachine.State.Destroyed
);
private static Set<String> allowedSessions; private static Set<String> allowedSessions;
@Override @Override
@ -130,13 +134,6 @@ public class ConsoleAccessManagerImpl extends ManagerBase implements ConsoleAcce
return new ConsoleEndpoint(false, null, "Permission denied"); return new ConsoleEndpoint(false, null, "Permission denied");
} }
if (BooleanUtils.isTrue(ConsoleAccessManager.ConsoleProxyExtraSecurityValidationEnabled.value()) &&
StringUtils.isBlank(extraSecurityToken)) {
String errorMsg = "Extra security validation is enabled but the extra token is missing";
s_logger.error(errorMsg);
return new ConsoleEndpoint(false, errorMsg);
}
String sessionUuid = UUID.randomUUID().toString(); String sessionUuid = UUID.randomUUID().toString();
return generateAccessEndpoint(vmId, sessionUuid, extraSecurityToken, clientAddress); return generateAccessEndpoint(vmId, sessionUuid, extraSecurityToken, clientAddress);
} catch (Exception e) { } catch (Exception e) {
@ -207,15 +204,23 @@ public class ConsoleAccessManagerImpl extends ManagerBase implements ConsoleAcce
throw new CloudRuntimeException(msg); throw new CloudRuntimeException(msg);
} }
if (vm.getHostId() == null) { String vmUuid = vm.getUuid();
msg = "VM " + vmId + " lost host info, sending blank response for console access request"; if (unsupportedConsoleVMState.contains(vm.getState())) {
msg = "VM " + vmUuid + " must be running to connect console, sending blank response for console access request";
s_logger.warn(msg); s_logger.warn(msg);
throw new CloudRuntimeException(msg); throw new CloudRuntimeException(msg);
} }
HostVO host = managementServer.getHostBy(vm.getHostId()); Long hostId = vm.getState() != VirtualMachine.State.Migrating ? vm.getHostId() : vm.getLastHostId();
if (hostId == null) {
msg = "VM " + vmUuid + " lost host info, sending blank response for console access request";
s_logger.warn(msg);
throw new CloudRuntimeException(msg);
}
HostVO host = managementServer.getHostBy(hostId);
if (host == null) { if (host == null) {
msg = "VM " + vmId + "'s host does not exist, sending blank response for console access request"; msg = "VM " + vmUuid + "'s host does not exist, sending blank response for console access request";
s_logger.warn(msg); s_logger.warn(msg);
throw new CloudRuntimeException(msg); throw new CloudRuntimeException(msg);
} }
@ -482,13 +487,4 @@ public class ConsoleAccessManagerImpl extends ManagerBase implements ConsoleAcce
} }
} }
@Override
public String getConfigComponentName() {
return ConsoleAccessManagerImpl.class.getSimpleName();
}
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey[] { ConsoleProxyExtraSecurityValidationEnabled };
}
} }

View File

@ -28,7 +28,6 @@
<script> <script>
import { SERVER_MANAGER } from '@/store/mutation-types' import { SERVER_MANAGER } from '@/store/mutation-types'
import { api } from '@/api' import { api } from '@/api'
import { uuid } from 'vue-uuid'
export default { export default {
name: 'Console', name: 'Console',
@ -44,24 +43,12 @@ export default {
}, },
data () { data () {
return { return {
url: '', url: ''
tokenValidationEnabled: false
} }
}, },
created () {
this.verifyExtraValidationEnabled()
},
methods: { methods: {
verifyExtraValidationEnabled () {
api('listConfigurations', { name: 'consoleproxy.extra.security.validation.enabled' }).then(json => {
this.tokenValidationEnabled = json?.listconfigurationsresponse?.configuration && json?.listconfigurationsresponse?.configuration[0]?.value === 'true'
})
},
consoleUrl () { consoleUrl () {
const params = {} const params = {}
if (this.tokenValidationEnabled) {
params.token = uuid.v4()
}
params.virtualmachineid = this.resource.id params.virtualmachineid = this.resource.id
api('createConsoleEndpoint', params).then(json => { api('createConsoleEndpoint', params).then(json => {
this.url = (json && json.createconsoleendpointresponse) ? json.createconsoleendpointresponse.consoleendpoint.url : '#/exception/404' this.url = (json && json.createconsoleendpointresponse) ? json.createconsoleendpointresponse.consoleendpoint.url : '#/exception/404'