package io.cattle.platform.servicediscovery.api.filter; import static io.cattle.platform.core.model.tables.ServiceTable.*; import io.cattle.platform.core.addon.LbConfig; import io.cattle.platform.core.constants.ServiceConstants; import io.cattle.platform.core.dao.ServiceDao; import io.cattle.platform.core.model.Certificate; import io.cattle.platform.core.model.Service; import io.cattle.platform.iaas.api.filter.common.AbstractDefaultResourceManagerFilter; import io.cattle.platform.json.JsonMapper; import io.cattle.platform.object.ObjectManager; import io.cattle.platform.object.util.DataAccessor; import io.cattle.platform.servicediscovery.api.service.ServiceDiscoveryApiService; 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 io.github.ibuildthecloud.gdapi.validation.ValidationErrorCodes; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import javax.inject.Named; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.TransformerUtils; import org.apache.commons.lang.StringUtils; @Named public class LoadBalancerServiceCertificateRemoveFilter extends AbstractDefaultResourceManagerFilter { @Inject ObjectManager objectManager; @Inject ServiceDao svcDao; @Inject JsonMapper jsonMapper; @Inject ServiceDiscoveryApiService sdService; @Override public Class<?>[] getTypeClasses() { return new Class<?>[] { Certificate.class }; } @Override public Object delete(String type, String id, ApiRequest request, ResourceManager next) { validateIfCertificateInUse(id); return super.delete(type, id, request, next); } @SuppressWarnings("unchecked") protected void validateIfCertificateInUse(String certificateId) { Certificate cert = objectManager.loadResource(Certificate.class, certificateId); List<String> serviceNames = new ArrayList<>(); List<Service> lbServices = objectManager.find(Service.class, SERVICE.ACCOUNT_ID, cert.getAccountId(), SERVICE.REMOVED, null, SERVICE.KIND, ServiceConstants.KIND_LOAD_BALANCER_SERVICE); for (Service lbService : lbServices) { if (sdService.isV1LB(lbService)) { List<Long> certIds = (List<Long>) CollectionUtils.collect( svcDao.getLoadBalancerServiceCertificates(lbService), TransformerUtils.invokerTransformer("getId")); Certificate defaultCert = svcDao.getLoadBalancerServiceDefaultCertificate(lbService); if (defaultCert != null) { certIds.add(defaultCert.getId()); } if (certIds.contains(cert.getId())) { serviceNames.add(lbService.getName()); } } else { // get from lb config LbConfig lbConfig = DataAccessor.field(lbService, ServiceConstants.FIELD_LB_CONFIG, jsonMapper, LbConfig.class); if (lbConfig == null) { continue; } List<Long> certIds = new ArrayList<>(); if (lbConfig.getCertificateIds() != null) { certIds.addAll(certIds); } if (lbConfig.getDefaultCertificateId() != null) { certIds.add(lbConfig.getDefaultCertificateId()); } if (certIds.contains(cert.getId())) { serviceNames.add(lbService.getName()); } } } if (!serviceNames.isEmpty()) { String serviceNameStr = StringUtils.join(serviceNames, ","); throw new ClientVisibleException(ResponseCodes.METHOD_NOT_ALLOWED, ValidationErrorCodes.INVALID_ACTION, "Certificate is in use by load balancer services: " + serviceNameStr, null); } } @Override public Object resourceAction(String type, ApiRequest request, ResourceManager next) { if (request.getAction().equalsIgnoreCase("remove")) { validateIfCertificateInUse(request.getId()); } return super.resourceAction(type, request, next); } }