package io.cattle.platform.iaas.api.credential;
import io.cattle.platform.api.link.LinkHandler;
import io.cattle.platform.core.constants.AccountConstants;
import io.cattle.platform.core.constants.CredentialConstants;
import io.cattle.platform.core.model.Account;
import io.cattle.platform.core.model.Credential;
import io.cattle.platform.object.ObjectManager;
import io.cattle.platform.server.context.ServerContext;
import io.cattle.platform.server.context.ServerContext.BaseProtocol;
import io.cattle.platform.token.CertSet;
import io.cattle.platform.token.impl.RSAKeyProvider;
import io.github.ibuildthecloud.gdapi.context.ApiContext;
import io.github.ibuildthecloud.gdapi.exception.ClientVisibleException;
import io.github.ibuildthecloud.gdapi.id.IdFormatter;
import io.github.ibuildthecloud.gdapi.request.ApiRequest;
import io.github.ibuildthecloud.gdapi.util.ResponseCodes;
import java.io.IOException;
import java.net.URL;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ApiKeyCertificateDownloadLinkHandler implements LinkHandler {
private static final Logger log = LoggerFactory.getLogger(ApiKeyCertificateDownloadLinkHandler.class);
@Inject
RSAKeyProvider keyProvider;
@Inject
ObjectManager objectManager;
@Override
public String[] getTypes() {
return new String[] { "apiKey", CredentialConstants.TYPE };
}
@Override
public boolean handles(String type, String id, String link, ApiRequest request) {
return CredentialConstants.LINK_CERTIFICATE.equalsIgnoreCase(link);
}
@Override
public Object link(String name, Object obj, ApiRequest request) throws IOException {
if (obj instanceof Credential) {
Credential cred = (Credential)obj;
String publicValue = cred.getPublicValue();
String secretValue = cred.getSecretValue();
if (secretValue == null || publicValue == null) {
return null;
}
try {
String[] sans = new String[0];
Account account = objectManager.loadResource(Account.class, cred.getAccountId());
if (account != null && AccountConstants.SERVICE_KIND.equals(account.getKind())) {
Set<String> sanSet = new LinkedHashSet<>();
URL url = new URL(request.getResponseUrlBase());
sanSet.add(url.getHost());
url = new URL(ServerContext.getHostApiBaseUrl(BaseProtocol.HTTP));
sanSet.add(url.getHost());
sanSet.add("IP:127.0.0.1");
sanSet.add("localhost");
sans = sanSet.toArray(new String[sanSet.size()]);
}
CertSet cert = keyProvider.generateCertificate(publicValue, sans);
prepareRequest(getFilename(cred, request), request);
HttpServletResponse response = request.getServletContext().getResponse();
cert.writeZip(response.getOutputStream());
} catch (Exception e) {
log.error("Failed to create certificate", e);
throw new ClientVisibleException(ResponseCodes.INTERNAL_SERVER_ERROR,
"CertCreationError", "Failed to create certificate", e.getMessage());
}
return new Object();
}
return null;
}
public static void prepareRequest(String filename, ApiRequest request) throws IOException {
HttpServletResponse response = request.getServletContext().getResponse();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
response.setHeader("Cache-Control", "private");
response.setHeader("Pragma", "private");
response.setHeader("Expires", "Wed 24 Feb 1982 18:42:00 GMT");
}
protected String getFilename(Credential cred, ApiRequest request) {
String name = cred.getName();
if (StringUtils.isBlank(name)) {
IdFormatter formatter = ApiContext.getContext().getIdFormatter();
Object id = formatter.formatId(cred.getKind(), cred.getId());
return "certificate-" + id + ".zip";
} else {
return name.toLowerCase().trim().replaceAll("[^a-zA-Z0-9]", "_") + ".zip";
}
}
}