.gitignore
.. .. @@ -3,3 +3,4 @@ 3 3 /.settings 4 4 /.classpath 5 5 /.project 6 +/doc/javadocetc/build/files/README.md
.. .. @@ -0,0 +1,185 @@ 1 +#SeCuris client2 +3 +##Usage securis-cient API4 +5 +The applications that need to manage licenses should use the class ```net.curisit.securis.LicenseManager ```6 +7 +There are 3 actions that the application can execute in the API:8 +9 +* Validate license file (```LicenseManager#validateLicense(...)```)10 +* Request a license file to License Server (not implemented yet) (```LicenseManager#requestLicense()```)11 +* Renew a license calling to License Server (not implemented yet) (```LicenseManager#renew(...)```)12 +13 +Currently, there is no server communication (License server API is not implemented yet), so, only local actions are available.14 +15 +____16 +17 +*Config file*18 +19 +20 +The SeCuris client library needs a config file that *has to be located in classpath*, in "```/securis-client.properties```"21 +22 +There are 3 parameters in the config file:23 +24 +```25 +public.key.file = /Path/to/public/key/file/securis.pub26 +app.code = AP0127 +customer.code = XX28 +```29 +30 +* ```public.key.file```: Public key file to validate the signed license file.31 +* ```app.code```: Code to identify the applciation, It will be given by SeCuris administrator32 +* ```customer.code```: Code to identify the customer where the application is deployed, this code will be given by SeCuris adminsitrator.33 +34 +All parameters are mandatory35 +36 +### Validate license file37 +38 +Validate the current license is as simple as call to ```validateLicense()```method passing it the license file location.39 +40 +For instance:41 +42 +```43 + File file = new File("path_to_license.lic_file");44 + try {45 + LicenseManager.getInstance().validateLicense(file);46 + log.info("License file {} is valid", file.getAbsolutePath());47 + } catch (SeCurisException e) {48 + log.info("License file {} is NOT valid", file.getAbsolutePath());49 + }50 +51 +```52 +53 +If license file is not valid an exception is thrown. The application can store the license file in whatever place in filesystem.54 +55 +56 +### Request a new license57 +58 +*THIS ACTION IS NOT YET IMPLEMENTED*59 +60 +The method to get a new license doesn't need parameters, the request data is generated by the method using the host hardware info and other paramters as application and customer code.61 +62 +```63 + try {64 + LicenseBean lic = LicenseManager.getInstance().requestLicense();65 + log.info("License {} got from server sucessfully", lic);66 + LicenseManager.getInstance().save(lic, new File("path_to_license.lic_file"));67 + } catch (SeCurisException e) {68 + log.info("Error getting License: " + e);69 + }70 +71 +```72 +73 +### Renew an existing license74 +75 +*THIS ACTION IS NOT YET IMPLEMENTED*76 +77 +All licenses have an expiration date, the application should ask for a new license to server before it expires.78 +79 +```80 + try {81 + File licenseFile = new File("path_to_license.lic_file");82 + LicenseBean lic = LicenseManager.getInstance().load(licenseFile);83 + long MONTH_LIMIT_MS = 30 * 24 * 3600 * 1000;84 + if (licBean.getExpirationDate().before(new Date(new Date().getTime() + MONTH_LIMIT_MS))) {85 + LicenseBean newLic = LicenseManager.getInstance().renew(licenseFile);86 + LicenseManager.getInstance().save(newLic, licenseFile);87 + }88 + } catch (SeCurisException e) {89 + log.info("Error renewing License: " + e);90 + }91 +92 +```93 +94 +The application will check if the expiration date is close (in the example we've used a month as date limit) and then it will ask for a new license. The ```renew()``` method will validate the current license, if it is not valid an exception will be launch.95 +96 +97 +##Usage securis-cient CLI98 +99 +The securis-client tool also provides a CLI (Command Line Interface) to be used by an administrator outside of application, we can use the same actons that from API and some additional one.100 +101 +*NOTE:* The file ```securis.sh```used in following examples are not included, but can be created easily, for instance:102 +103 +```104 +#!/bin/bash105 +export CLASSPATH=libs/*.jar106 +java -cp $CLASSPATH -jar libs/securis-client-*.jar $@107 +```108 +109 +110 +### Creation of a request file111 +112 +For a manual activation, a request file should be sent to SeCuris administrator, to create a request file we can execute:113 +114 +```115 + $ ./securis.sh --gen_request --rfile=/tmp/curisapp.req116 +117 +```118 +119 +### Validate license file120 +121 +```122 + $ ./securis.sh --validate=/path/to/license/file/curisapp.lic123 +124 +```125 +126 +### Request a new license to server127 +128 +```129 + $ ./securis.sh --create=/path/to/license/file/curisapp.lic --server="http://server:0000/securis/api/create"130 +131 +```132 +133 +### Renew an existing license134 +135 +```136 + $ securis.sh --renew=/path/to/license/file/curisapp.lic --server="http://server:0000/securis/api/create"137 +138 +```139 +140 +##Request and License files141 +142 +The request and license file are json files and the content can be read easily143 +144 +Example of request file:145 +146 +```147 +{148 + "customerCode" : "BP01",149 + "appCode" : "CD01",150 + "macAddresses" : [ "E0-F8-47-43-E1-D2", "70-CD-60-F2-A5-4B" ],151 + "osName" : "Mac OS X",152 + "arch" : "x86_64"153 +}154 +155 +```156 +157 +158 +Example of license file:159 +160 +```161 +{162 + "licenseCode" : "LIC-9812987123-12837129873",163 + "licenseType" : "L01",164 + "expirationDate" : 1393266018149,165 + "appCode" : "CD01",166 + "arch" : "x86_64",167 + "osName" : "Mac OS X",168 + "customerCode" : "BP01",169 + "macAddresses" : [ "E0-F8-47-43-E1-D2", "70-CD-60-F2-A5-4B" ],170 + "metadata" : {171 + "maxInstances" : 12,172 + "maxUsers" : 23173 + },174 + "signature" : "bZTzW5JYTIQOclwObnBXu250IB5o2xHhIbWyHaIf57H+0Xr7Gqtphj0/nT/SSfr6yMjPVaZ/BW7d\r\nFX/I7bA8xMfIXMpPG9qcqna2iRxwKw/j8rROydHs4vn9c1VYGpDG0NowJewdJJyKTSrlMvUDM/9L\r\n2VPVQl11UwgHm+AkLD42Qj/UassBrpdnoU4PuAn8Odc8hXnnj2jiUUeQFrK0DHMAaewOw+lKY1yfB\r\nCF/5y/z+6iyBTvrGw2kBh521Yu7siL9NK7KtE7R3t9h8+XIozgXdunMRxZ1+jLwKJKK+l7InY7UA\r\nsDgXSJofR/S2/hwKkXiAiSfAUt04rnMHTrRtIQ==\r\n"175 +}176 +177 +```178 +179 +180 +181 +182 +183 +184 +185 +src/main/java/net/curisit/securis/License.java
.. .. @@ -103,8 +103,8 @@ 103 103 } 104 104 105 105 if (cmd.hasOption('r')) { 106 - String licFilename = cmd.getOptionValue("sync");107 - checkMandatoryParameter(licFilename, "sync");106 + String licFilename = cmd.getOptionValue("renew");107 + checkMandatoryParameter(licFilename, "renew");108 108 String server = cmd.getOptionValue("server"); 109 109 checkMandatoryParameter(server, "server"); 110 110 .. .. @@ -176,7 +176,7 @@ 176 176 options.addOption(OptionBuilder.withArgName("lic_file").withLongOpt("validate").withDescription("Validate lic file.").hasArg(true).create('l')); 177 177 178 178 options.addOption("g", "gen_request", false, "Generate request file. If --rfile parameter is missing then It is generated in current directory."); 179 - options.addOption("c", "create", false, "Request a license file from server. --rfile and --server parameters are mandatory.");179 + options.addOption(OptionBuilder.withArgName("lic_file").withLongOpt("create").withDescription("Request a license file from server. --server parameters is mandatory.").hasArg(true).create('c'));180 180 options.addOption("t", "test_lc", false, "Test if License Server (LC) is available. --server parameter is mandatory."); 181 181 options.addOption(OptionBuilder.withArgName("lic_file").withLongOpt("renew").withDescription("Synchronize/renew the current license file. --server parameter is mandatory.").hasArg(true).create('r')); 182 182 src/main/java/net/curisit/securis/LicenseManager.java
.. .. @@ -2,20 +2,30 @@ 2 2 3 3 import java.io.File; 4 4 import java.io.IOException; 5 +import java.io.UnsupportedEncodingException;6 +import java.nio.file.Files;7 +import java.nio.file.Paths;8 +import java.nio.file.StandardOpenOption;5 9 6 10 import net.curisit.securis.beans.LicenseBean; 7 11 import net.curisit.securis.beans.RequestBean; 12 +import net.curisit.securis.beans.SignedLicenseBean;8 13 import net.curisit.securis.utils.JsonUtils; 9 14 import net.curisit.securis.utils.Params; 15 +import net.curisit.securis.utils.SignatureHelper;10 16 11 17 import org.apache.commons.io.FileUtils; 18 +import org.apache.logging.log4j.LogManager;19 +import org.apache.logging.log4j.Logger;12 20 13 21 /** 14 - * Manage all licenses tasks, just like, validation, sync, requesting, ...22 + * Manage all licenses tasks, just like validation, renew, requesting, ...15 23 * 16 24 * @author roberto <roberto.sanchez@curisit.net> 17 25 */ 18 26 public class LicenseManager { 27 +28 + private static final Logger log = LogManager.getLogger(License.class);19 29 20 30 private static LicenseManager singleton = new LicenseManager(); 21 31 .. .. @@ -24,6 +34,23 @@ 24 34 25 35 public static LicenseManager getInstance() { 26 36 return singleton; 37 + }38 +39 + /**40 + * Loads a license from file41 + *42 + * @param licFile43 + * @return The license bean44 + * @throws SeCurisException45 + */46 + public LicenseBean load(File licFile) throws SeCurisException {47 + LicenseBean licBean;48 + try {49 + licBean = JsonUtils.json2object(FileUtils.readFileToString(licFile), LicenseBean.class);50 + } catch (IOException e) {51 + throw new SeCurisException("Error getting license data from file: " + licFile, e);52 + }53 + return licBean;27 54 } 28 55 29 56 /** .. .. @@ -42,17 +69,56 @@ 42 69 * @throws SeCurisException 43 70 */ 44 71 public LicenseBean validateLicense(File licFile) throws SeCurisException { 45 - LicenseBean licBean;46 - try {47 - licBean = JsonUtils.json2object(FileUtils.readFileToString(licFile), LicenseBean.class);48 - } catch (IOException e) {49 - throw new SeCurisException("Error getting license data from file: " + licFile, e);50 - }72 + LicenseBean licBean = load(licFile);51 73 SignatureHelper.getInstance().validateSignature(licBean); 52 74 LicenseValidator.getInstance().validateHW(licBean, Params.get(Params.KEYS.APPLICATION_CODE), Params.get(Params.KEYS.CUSTOMER_CODE)); 53 75 LicenseValidator.getInstance().validateLogo(licBean); 54 76 55 77 return licBean; 78 + }79 +80 + /**81 + * Request to server for a valid license82 + *83 + * @return The license bean returned by the server84 + * @throws SeCurisException85 + */86 + public LicenseBean requestLicense() throws SeCurisException {87 + RequestBean req = ReqGenerator.getInstance().createRequest(Params.get(Params.KEYS.APPLICATION_CODE), Params.get(Params.KEYS.CUSTOMER_CODE));88 + if (true)89 + throw new SeCurisException("Action not implemented yet");90 + LicenseBean lic = requestLicenseToServer(req);91 + return lic;92 + }93 +94 + /**95 + * Generate a license file using a {@link LicenseBean}96 + *97 + * @param license98 + * @param file99 + * @throws SeCurisException100 + */101 + public void save(LicenseBean license, File file) throws SeCurisException {102 + SignedLicenseBean signedLic = new SignedLicenseBean(license);103 + byte[] json;104 + try {105 + json = JsonUtils.toJSON(signedLic, true).getBytes("utf-8");106 + Files.write(Paths.get(file.toURI()), json, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);107 + } catch (UnsupportedEncodingException e) {108 + log.error("Error creating json doc from license: " + license, e);109 + throw new SeCurisException("Error creating json doc from license: " + license, e);110 + } catch (IOException e) {111 + log.error("Error creating license file: " + file, e);112 + throw new SeCurisException("Error creating json doc from license: " + license, e);113 + }114 +115 + log.debug("License saved in {}", file);116 +117 + }118 +119 + private LicenseBean requestLicenseToServer(RequestBean req) {120 + // TODO Prepare call to server sending the request bean to get a valid license121 + return null;56 122 } 57 123 58 124 /** .. .. @@ -79,7 +145,7 @@ 79 145 * @return New license bean if server creates a new one, otherwise the same current License bean will be returned 80 146 * @throws SeCurisException 81 147 */ 82 - public LicenseBean sync(File licenseFile) throws SeCurisException {148 + public LicenseBean renew(File licenseFile) throws SeCurisException {83 149 LicenseBean lic = validateLicense(licenseFile); 84 150 if (true) 85 151 throw new SeCurisException("Action not implemented yet"); src/main/java/net/curisit/securis/ReqGenerator.java
.. .. @@ -9,6 +9,7 @@ 9 9 import java.nio.file.StandardOpenOption; 10 10 11 11 import net.curisit.securis.beans.RequestBean; 12 +import net.curisit.securis.utils.HWInfo;12 13 import net.curisit.securis.utils.JsonUtils; 13 14 import net.curisit.securis.utils.LicUtils; 14 15 src/patch/java/net/curisit/securis/beans/SignedLicenseBean.javasimilarity index 100%rename from src/patch/java/net/curisit/securis/beans/SignedLicenseBean.javarename to src/main/java/net/curisit/securis/beans/SignedLicenseBean.java
src/main/java/net/curisit/securis/utils/SignatureHelper.java
.. .. @@ -36,7 +36,7 @@ 36 36 private static SignatureHelper singleton = new SignatureHelper(); 37 37 38 38 private static final String DEFAULT_ALGORITHM = "RSA"; 39 - protected static final String SIGNATURE_GENERATION_ALGORITHM = "SHA256withRSA";39 + public static final String SIGNATURE_GENERATION_ALGORITHM = "SHA256withRSA";40 40 41 41 private SignatureHelper() { 42 42 } .. .. @@ -45,7 +45,7 @@ 45 45 return singleton; 46 46 } 47 47 48 - protected void prepareSignature(Signature signature, LicenseBean licBean) throws SeCurisException {48 + public void prepareSignature(Signature signature, LicenseBean licBean) throws SeCurisException {49 49 try { 50 50 log.info("JSON: {}", JsonUtils.toJSON(licBean)); 51 51 signature.update(JsonUtils.toJSON(licBean).getBytes("utf-8")); .. .. @@ -98,7 +98,7 @@ 98 98 return publicKey; 99 99 } 100 100 101 - protected PrivateKey generatePrivateKey(File privateKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {101 + public PrivateKey generatePrivateKey(File privateKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {102 102 String privKeyBase64 = FileUtils.readFileToString(privateKeyFile); 103 103 int from = privKeyBase64.indexOf('\n'); 104 104 int to = privKeyBase64.indexOf("-----END", from); .. .. @@ -111,7 +111,7 @@ 111 111 return privateKey; 112 112 } 113 113 114 - private KeyPair generateKeyPair(File privateKeyFile, File publicKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {114 + public KeyPair generateKeyPair(File privateKeyFile, File publicKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {115 115 116 116 PublicKey publicKey = generatePublicKey(publicKeyFile); 117 117 PrivateKey privateKey = generatePrivateKey(privateKeyFile); src/patch/java/net/curisit/securis/LicenseGenerator.java
.. .. @@ -20,6 +20,7 @@ 20 20 import net.curisit.securis.beans.RequestBean; 21 21 import net.curisit.securis.beans.SignedLicenseBean; 22 22 import net.curisit.securis.utils.JsonUtils; 23 +import net.curisit.securis.utils.SignatureHelper;23 24 24 25 import org.apache.commons.net.util.Base64; 25 26 import org.apache.logging.log4j.LogManager;