package io.cattle.platform.host.api; import static io.cattle.platform.server.context.ServerContext.*; import io.cattle.platform.api.auth.Policy; import io.cattle.platform.api.utils.ApiUtils; import io.cattle.platform.core.constants.HostConstants; import io.cattle.platform.core.dao.AgentDao; import io.cattle.platform.core.model.Agent; import io.cattle.platform.core.model.Host; import io.cattle.platform.object.ObjectManager; import io.cattle.platform.server.context.ServerContext; import io.cattle.platform.token.TokenService; import io.github.ibuildthecloud.gdapi.exception.ClientVisibleException; import io.github.ibuildthecloud.gdapi.exception.ValidationErrorException; import io.github.ibuildthecloud.gdapi.request.ApiRequest; import io.github.ibuildthecloud.gdapi.request.resource.impl.AbstractNoOpResourceManager; import io.github.ibuildthecloud.gdapi.util.ResponseCodes; import io.github.ibuildthecloud.gdapi.validation.ValidationErrorCodes; import java.util.HashMap; import java.util.Map; import javax.inject.Inject; import org.apache.commons.lang3.StringUtils; public class HostApiProxyTokenManager extends AbstractNoOpResourceManager { private static final String VERIFY_AGENT = "CantVerifyAgent"; @Inject TokenService tokenService; @Inject AgentDao agentDao; @Inject ObjectManager objectManager; @Override public Class<?>[] getTypeClasses() { return new Class<?>[] { HostApiProxyTokenImpl.class }; } @Override protected Object createInternal(String type, ApiRequest request) { HostApiProxyToken p = request.proxyRequestObject(HostApiProxyToken.class); validate(p); HostApiProxyTokenImpl token = new HostApiProxyTokenImpl(); token.setToken(getToken(p.getReportedUuid())); token.setReportedUuid(p.getReportedUuid()); StringBuilder buffer = new StringBuilder(); switch (getHostApiProxyMode()) { case HOST_API_PROXY_MODE_HA: if (StringUtils.isNotBlank(HostApiUtils.HOST_API_PROXY_HOST.get())) { String scheme = StringUtils.startsWithIgnoreCase(request.getResponseUrlBase(), "https") ? "wss://" : "ws://"; buffer.append(scheme).append(HostApiUtils.HOST_API_PROXY_HOST.get()); break; } // Purposefully fall through case HOST_API_PROXY_MODE_EMBEDDED: if (ServerContext.isCustomApiHost()) { buffer.append(ServerContext.getHostApiBaseUrl(ServerContext.BaseProtocol.WEBSOCKET)); } else { buffer.append(request.getResponseUrlBase().replaceFirst("http", "ws")); } break; case HOST_API_PROXY_MODE_OFF: throw new ClientVisibleException(501, "HostApiProxyDisabled"); } if (buffer.length() <= 0) { throw new ClientVisibleException(ResponseCodes.INTERNAL_SERVER_ERROR, "CantConstructUrl"); } if ('/' == buffer.charAt(buffer.length() - 1)) { buffer.deleteCharAt(buffer.length() - 1); } String url = buffer.append(HostApiUtils.HOST_API_PROXY_BACKEND.get()).toString(); token.setUrl(url); return token; } protected String getToken(String reportedUuid) { Map<String, Object> data = new HashMap<String, Object>(); data.put(HostConstants.FIELD_REPORTED_UUID, reportedUuid); return tokenService.generateToken(data); } protected void validate(HostApiProxyToken proxyToken) { String reportedUuid = proxyToken.getReportedUuid(); Policy policy = ApiUtils.getPolicy(); Agent agent = objectManager.loadResource(Agent.class, policy.getOption(Policy.AGENT_ID)); if (agent == null) { throw new ClientVisibleException(ResponseCodes.FORBIDDEN, VERIFY_AGENT); } Map<String, Host> hosts = agentDao.getHosts(agent.getId()); Host host = hosts.get(reportedUuid); if (host == null) { throw new ValidationErrorException(ValidationErrorCodes.INVALID_REFERENCE, HostConstants.FIELD_REPORTED_UUID); } } }