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 org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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;
/**
* 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);
if (licBean.getActivationCode() != null) {
LicenseValidator.getInstance().validateHW(licBean, Params.get(Params.KEYS.APPLICATION_CODE), licBean.getActivationCode());
} else {
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;
}
/**
* Request to server for a valid license
*
* @return The license bean returned by the server
* @throws SeCurisException
*/
public SignedLicenseBean requestLicense(String nameOrReference, String email, String activationCode) throws SeCurisException {
RequestBean req = ReqGenerator.getInstance().createRequest(Params.get(Params.KEYS.APPLICATION_CODE), activationCode);
SignedLicenseBean lic = requestLicenseToServer(req, nameOrReference, email);
return lic;
}
/**
* Request to server for a valid license
*
* @return The license bean returned by the server
* @throws SeCurisException
*/
public SignedLicenseBean requestLicense(String activationCode) throws SeCurisException {
return requestLicense(null, null, activationCode);
}
/**
* 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;
}
/**
* 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, String activationCode) throws SeCurisException {
return createRequestFile(outputRequestFile, activationCode, null);
}
/**
* Creates a new request file with current hardware in the File passed as
* parameter
*
* @param outputRequestFile
* File where the request data will be saved
*
* @param activationCode
* Activation code provided be SeCurisadministrator
* @param appCode
* Application code to use, ignoring the code set in config file
* @return The generated request bean
* @throws SeCurisException
*/
public RequestBean createRequestFile(File outputRequestFile, String activationCode, String appCode) throws SeCurisException {
if (appCode == null) {
Params.get(Params.KEYS.APPLICATION_CODE);
}
RequestBean req = ReqGenerator.getInstance().createRequest(appCode, activationCode);
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 {
System.out.println("APPLICATION_CODE: " + Params.get(Params.KEYS.APPLICATION_CODE));
System.out.println("LICENSE_SERVER_URL: " + Params.get(Params.KEYS.LICENSE_SERVER_URL));
LicenseManager lm = LicenseManager.getInstance();
// LicenseBean lic =
// lm.requestLicense("aaf88d6c-6622-492a-93ec-10f3d1dc7120");
LicenseBean lic = lm.requestLicense("Rob", "rsanchez@curisit.net");
System.out.println(lic.getLicenseCode() + " " + lic.getExpirationDate());
// LicenseBean lic = lm.
}
}