package net.curisit.securis;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import net.curisit.securis.ConnectionManager.Command;
import net.curisit.securis.beans.LicenseBean;
import net.curisit.securis.beans.RequestBean;
import net.curisit.securis.beans.SignedLicenseBean;
import net.curisit.securis.beans.StatusBean;
import net.curisit.securis.utils.JsonUtils;
import net.curisit.securis.utils.Params;
import net.curisit.securis.utils.SignatureHelper;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Manage all licenses tasks, just like validation, renew, requesting, ...
*
* @author roberto
*/
public class LicenseManager {
private static final Logger LOG = LogManager.getLogger(LicenseManager.class);
private static LicenseManager singleton = new LicenseManager();
public static final String PING_MESSAGE = "SeCuris API OK";
public static final String HEADER_LICENSE_NAME_OR_REFERENCE = "X-SECURIS-LIC-NAMEREF";
public static final String HEADER_LICENSE_EMAIL = "X-SECURIS-LIC-EMAIL";
private LicenseManager() {}
public static LicenseManager getInstance() {
return singleton;
}
/**
* Loads a license from file
*
* @param licFile
* @return The license bean
* @throws SeCurisException
*/
public LicenseBean load(File licFile) throws SeCurisException {
LicenseBean licBean;
try {
licBean = JsonUtils.json2object(FileUtils.readFileToString(licFile), LicenseBean.class);
} catch (IOException e) {
throw new SeCurisException("Error getting license data from file: " + licFile, e);
}
return licBean;
}
/**
* Validates the license stored in {@code licFile} and get the corresponding LicenseBean
*
* The validation includes:
*
* - Signature
* - HW data
* - Logo CRC
*
*
*
* @param licFile
* @return The license bean stored in file
* @throws SeCurisException
*/
public LicenseBean validateLicense(File licFile) throws SeCurisException {
return validateLicense(licFile, false);
}
/**
* Validates the license stored in {@code licFile} and get the corresponding LicenseBean. The License date is not validated
*
* The validation includes:
*
* - Signature
* - HW data
* - Logo CRC
*
*
*
* @param licFile
* @return The license bean stored in file
* @throws SeCurisException
*/
public LicenseBean validateLicense(File licFile, boolean excludeDateValidation) throws SeCurisException {
LicenseBean licBean = load(licFile);
SignatureHelper.getInstance().validateSignature(licBean);
LicenseValidator.getInstance().validateHW(licBean, Params.get(Params.KEYS.LIC_TYPE_CODE, Params.get(Params.KEYS.APPLICATION_CODE)), Params.get(Params.KEYS.CUSTOMER_CODE), Params.get(Params.KEYS.PACK_CODE));
LicenseValidator.getInstance().validateLogo(licBean);
if (!excludeDateValidation) {
if (new Date().after(licBean.getExpirationDate())) {
throw new ExpiredLicenseException();
}
}
return licBean;
}
/**
* Request to server for a valid license
*
* @return The license bean returned by the server
* @throws SeCurisException
*/
public SignedLicenseBean requestLicense(String nameOrReference, String email) throws SeCurisException {
RequestBean req = ReqGenerator.getInstance().createRequest(Params.get(Params.KEYS.LIC_TYPE_CODE, Params.get(Params.KEYS.APPLICATION_CODE)), Params.get(Params.KEYS.CUSTOMER_CODE), Params.get(Params.KEYS.PACK_CODE));
SignedLicenseBean lic = requestLicenseToServer(req, nameOrReference, email);
return lic;
}
/**
* Generate a license file using a {@link LicenseBean}
*
* @param license
* @param file
* @throws SeCurisException
*/
public void save(LicenseBean license, File file) throws SeCurisException {
SignedLicenseBean signedLic = new SignedLicenseBean(license);
save(signedLic, file);
}
/**
* Generate a license file using a {@link LicenseBean}
*
* @param license
* @param file
* @throws SeCurisException
*/
public void save(SignedLicenseBean signedLic, File file) throws SeCurisException {
byte[] json;
try {
json = JsonUtils.toPrettyJSON(signedLic).getBytes("utf-8");
Files.write(Paths.get(file.toURI()), json, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (UnsupportedEncodingException e) {
LOG.error("Error creating json doc from license: " + signedLic, e);
throw new SeCurisException("Error creating json doc from license: " + signedLic, e);
} catch (IOException e) {
LOG.error("Error creating license file: " + file, e);
throw new SeCurisException("Error creating json doc from license: " + signedLic, e);
}
LOG.debug("License saved in {}", file);
}
private SignedLicenseBean requestLicenseToServer(RequestBean req, String nameOrReference, String email) throws SeCurisException {
Map headers = new HashMap();
headers.put(HEADER_LICENSE_NAME_OR_REFERENCE, nameOrReference);
headers.put(HEADER_LICENSE_EMAIL, email);
SignedLicenseBean lic = ConnectionManager.getInstance().executePost(Command.CREATE_LIC, SignedLicenseBean.class, req, headers);
return lic;
}
/**
* Creates a new request file with current hardware in the File passed as parameter
*
* @param outputRequestFile
* File where the request data will be saved
* @return The generated request bean
* @throws SeCurisException
*/
public RequestBean createRequestFile(File outputRequestFile) throws SeCurisException {
RequestBean req = ReqGenerator.getInstance().createRequest(Params.get(Params.KEYS.LIC_TYPE_CODE, Params.get(Params.KEYS.APPLICATION_CODE)), Params.get(Params.KEYS.CUSTOMER_CODE), Params.get(Params.KEYS.PACK_CODE));
ReqGenerator.getInstance().save(req, outputRequestFile);
return req;
}
/**
* Send the current license file to server, which is previously validated, to get a renewed one if it is prepared in server side.
*
* @param licenseFile
* Current and valid License file
* @return New license bean if server creates a new one, otherwise the same current License bean will be returned
* @throws SeCurisException
*/
public SignedLicenseBean renew(File licenseFile) throws SeCurisException {
LicenseBean lic = validateLicense(licenseFile, true);
SignedLicenseBean newLic = ConnectionManager.getInstance().executePost(Command.RENEW_LIC, SignedLicenseBean.class, lic);
return newLic;
}
/**
* Check on SeCuris server if current license is still valid in server DB.
*
* @param licenseFile
* @throws SeCurisException
*/
public void assertLicenseIsValid(File licenseFile) throws SeCurisException, IOException {
LicenseBean lic = validateLicense(licenseFile);
// We need to snd the signed version to validate signature on server
ConnectionManager.getInstance().executePost(Command.VALIDATE, LicenseBean.class, new SignedLicenseBean(lic));
}
public void testServer() throws SeCurisException {
StatusBean status = ConnectionManager.getInstance().executeGet(Command.TEST, StatusBean.class);
if (!PING_MESSAGE.equals(status.getMessage())) {
throw new SeCurisException("SeCuris Server is not running in given URL");
}
}
public static void main(String[] args) throws SeCurisException {
String filename = "/Users/rob/.doxr/doxr.lic";
if (filename == null)
filename = "./license.req";
File file = new File(filename);
LicenseManager.getInstance().validateLicense(file);
LOG.info("Validation Ok");
String r = "{\"licenseTypeCode\":\"DX01\",\"packCode\":\"DEVDX01\",\"arch\":\"x86_64\",\"osName\":\"darwin\",\"customerCode\":\"CIT\",\"macAddresses\":[\"60:c5:47:03:cf:c8\",\"b2:00:12:b6:88:e0\"]}";
RequestBean rb = JsonUtils.json2object(r, RequestBean.class);
System.out.println(rb);
LOG.info("Request file {} generated OK", file.getAbsolutePath());
}
}