package io.cattle.platform.docker.machine.api.filter;
import static io.cattle.platform.core.constants.MachineConstants.*;
import io.cattle.platform.api.utils.ApiUtils;
import io.cattle.platform.core.constants.AccountConstants;
import io.cattle.platform.core.constants.HostConstants;
import io.cattle.platform.core.constants.MachineConstants;
import io.cattle.platform.core.model.Host;
import io.cattle.platform.framework.secret.SecretsService;
import io.cattle.platform.iaas.api.filter.common.AbstractDefaultResourceManagerFilter;
import io.cattle.platform.object.util.DataAccessor;
import io.cattle.platform.util.type.CollectionUtils;
import io.github.ibuildthecloud.gdapi.exception.ClientVisibleException;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import io.github.ibuildthecloud.gdapi.request.resource.ResourceManager;
import io.github.ibuildthecloud.gdapi.util.ResponseCodes;
import java.io.IOException;
import java.util.Map;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MachineValidationFilter extends AbstractDefaultResourceManagerFilter {
private static final String DRIVER_CONFIG_EXACTLY_ONE_REQUIRED = "DriverConfigExactlyOneRequired";
private static final Logger log = LoggerFactory.getLogger(MachineValidationFilter.class);
@Inject
SecretsService secretsService;
@Override
public Class<?>[] getTypeClasses() {
return new Class<?>[] {Host.class};
}
@Override
public String[] getTypes() {
return new String[] { KIND_MACHINE };
}
@Override
public Object create(String type, ApiRequest request, ResourceManager next) {
// Don't validate hosts for v1 API
if (HostConstants.TYPE.equals(type) && ("v1".equals(request.getVersion()) ||
AccountConstants.SUPER_ADMIN_KIND.equals(request.getSchemaFactory().getId()))) {
return super.create(type, request, next);
}
Map<String, Object> data = CollectionUtils.toMap(request.getRequestObject());
boolean alreadyFound = false;
for (Map.Entry<String, Object> field : data.entrySet()) {
if (StringUtils.endsWithIgnoreCase(field.getKey(), CONFIG_FIELD_SUFFIX) && field.getValue() != null) {
if (alreadyFound) {
throw new ClientVisibleException(ResponseCodes.UNPROCESSABLE_ENTITY, DRIVER_CONFIG_EXACTLY_ONE_REQUIRED);
}
alreadyFound = true;
}
}
if (!alreadyFound) {
throw new ClientVisibleException(ResponseCodes.UNPROCESSABLE_ENTITY, DRIVER_CONFIG_EXACTLY_ONE_REQUIRED);
}
return super.create(type, request, next);
}
@Override
public Object update(String type, String id, ApiRequest request, ResourceManager next) {
Map<String, Object> data = CollectionUtils.toMap(request.getRequestObject());
String extracted = DataAccessor.fromMap(data).withKey(MachineConstants.EXTRACTED_CONFIG_FIELD).as(String.class);
if (extracted != null) {
try {
extracted = secretsService.encrypt(ApiUtils.getPolicy().getAccountId(), extracted);
} catch (IOException e) {
log.error("Failed to encrypt machine secrets", e);
throw new ClientVisibleException(ResponseCodes.INTERNAL_SERVER_ERROR, "FailedEncryption");
}
data.put(MachineConstants.EXTRACTED_CONFIG_FIELD, extracted);
}
return super.update(type, id, request, next);
}
}