From bc372a688bf2062ba1e7e2ef2f9e69123d7873db Mon Sep 17 00:00:00 2001
From: Roberto Sánchez <roberto.sanchez@curisit.net>
Date: Tue, 25 Feb 2014 10:11:57 +0000
Subject: [PATCH] #593 doc - Added HOW-TO doc

---
 src/main/java/net/curisit/securis/beans/SignedLicenseBean.java |    0 
 .gitignore                                                     |    1 
 etc/build/files/README.md                                      |  185 +++++++++++++++++++++++++++++++++++++
 src/main/java/net/curisit/securis/LicenseManager.java          |   82 ++++++++++++++-
 src/main/java/net/curisit/securis/ReqGenerator.java            |    1 
 src/main/java/net/curisit/securis/License.java                 |    6 
 src/main/java/net/curisit/securis/utils/SignatureHelper.java   |    8 
 src/patch/java/net/curisit/securis/LicenseGenerator.java       |    1 
 8 files changed, 269 insertions(+), 15 deletions(-)

diff --git a/.gitignore b/.gitignore
index f7619e3..0ab72a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
 /.settings
 /.classpath
 /.project
+/doc/javadoc
diff --git a/etc/build/files/README.md b/etc/build/files/README.md
new file mode 100644
index 0000000..1ffea7b
--- /dev/null
+++ b/etc/build/files/README.md
@@ -0,0 +1,185 @@
+#SeCuris client
+
+##Usage securis-cient API
+
+The applications that need to manage licenses should use the class ```net.curisit.securis.LicenseManager ```
+
+There are 3 actions that the application can execute in the API: 
+
+* Validate license file (```LicenseManager#validateLicense(...)```)
+* Request a license file to License Server (not implemented yet)  (```LicenseManager#requestLicense()```)
+* Renew a license calling to License Server (not implemented yet)  (```LicenseManager#renew(...)```)
+
+Currently, there is no server communication (License server API is not implemented yet), so, only local actions are available.
+
+____
+
+*Config file*
+
+
+The SeCuris client library needs a config file that *has to be located in classpath*, in "```/securis-client.properties```"
+
+There are 3 parameters in the config file:
+
+```
+public.key.file = /Path/to/public/key/file/securis.pub
+app.code = AP01
+customer.code = XX
+```
+
+* ```public.key.file```: Public key file to validate the signed license file.
+* ```app.code```: Code to identify the applciation, It will be given by SeCuris administrator
+* ```customer.code```: Code to identify the customer where the application is deployed, this code will be given by SeCuris adminsitrator.
+
+All parameters are mandatory
+
+### Validate license file
+
+Validate the current license is as simple as call to ```validateLicense()```method passing it the license file location.
+
+For instance:
+
+```
+	File file = new File("path_to_license.lic_file");
+	try {
+		LicenseManager.getInstance().validateLicense(file);
+		log.info("License file {} is valid", file.getAbsolutePath());
+	} catch (SeCurisException e) {
+		log.info("License file {} is NOT valid", file.getAbsolutePath());
+	}
+
+```
+
+If license file is not valid an exception is thrown. The application can store the license file in whatever place in filesystem.
+
+
+### Request a new license
+
+*THIS ACTION IS NOT YET IMPLEMENTED*
+
+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.
+
+```
+	try {
+		LicenseBean lic = LicenseManager.getInstance().requestLicense();
+		log.info("License {} got from server sucessfully", lic);
+		LicenseManager.getInstance().save(lic, new File("path_to_license.lic_file"));
+	} catch (SeCurisException e) {
+		log.info("Error getting License: " + e);
+	}
+
+```
+
+### Renew an existing license
+
+*THIS ACTION IS NOT YET IMPLEMENTED*
+
+All licenses have an expiration date, the application should ask for a new license to server before it expires.
+
+```
+	try {
+		File licenseFile = new File("path_to_license.lic_file");
+		LicenseBean lic = LicenseManager.getInstance().load(licenseFile);
+		long MONTH_LIMIT_MS = 30 * 24 * 3600 * 1000;
+		if (licBean.getExpirationDate().before(new Date(new Date().getTime() + MONTH_LIMIT_MS))) {
+			LicenseBean newLic = LicenseManager.getInstance().renew(licenseFile);
+			LicenseManager.getInstance().save(newLic, licenseFile);
+		}
+	} catch (SeCurisException e) {
+		log.info("Error renewing License: " + e);
+	}
+
+```
+
+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.
+
+
+##Usage securis-cient CLI
+
+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.
+
+*NOTE:* The file ```securis.sh```used in following examples are not included, but can be created easily, for instance:
+
+```
+#!/bin/bash
+export CLASSPATH=libs/*.jar
+java -cp $CLASSPATH -jar libs/securis-client-*.jar $@
+```
+
+
+### Creation of a request file
+
+For a manual activation, a request file should be sent to SeCuris administrator, to create a request file we can execute:
+
+```
+    $ ./securis.sh --gen_request --rfile=/tmp/curisapp.req
+    
+```
+
+### Validate license file
+
+```
+    $ ./securis.sh --validate=/path/to/license/file/curisapp.lic
+    
+```
+
+### Request a new license to server
+
+```
+    $ ./securis.sh --create=/path/to/license/file/curisapp.lic --server="http://server:0000/securis/api/create"
+    
+```
+
+### Renew an existing license
+
+```
+    $ securis.sh --renew=/path/to/license/file/curisapp.lic --server="http://server:0000/securis/api/create"
+    
+```
+
+##Request and License files
+
+The request and license file are json files and the content can be read easily
+
+Example of request file:
+
+```
+{
+  "customerCode" : "BP01",
+  "appCode" : "CD01",
+  "macAddresses" : [ "E0-F8-47-43-E1-D2", "70-CD-60-F2-A5-4B" ],
+  "osName" : "Mac OS X",
+  "arch" : "x86_64"
+}
+
+```
+
+
+Example of license file:
+
+```
+{
+  "licenseCode" : "LIC-9812987123-12837129873",
+  "licenseType" : "L01",
+  "expirationDate" : 1393266018149,
+  "appCode" : "CD01",
+  "arch" : "x86_64",
+  "osName" : "Mac OS X",
+  "customerCode" : "BP01",
+  "macAddresses" : [ "E0-F8-47-43-E1-D2", "70-CD-60-F2-A5-4B" ],
+  "metadata" : {
+    "maxInstances" : 12,
+    "maxUsers" : 23
+  },
+  "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"
+}
+
+```
+
+
+
+
+
+
+
+
diff --git a/src/main/java/net/curisit/securis/License.java b/src/main/java/net/curisit/securis/License.java
index 4ad5059..605b50a 100644
--- a/src/main/java/net/curisit/securis/License.java
+++ b/src/main/java/net/curisit/securis/License.java
@@ -103,8 +103,8 @@
 			}
 
 			if (cmd.hasOption('r')) {
-				String licFilename = cmd.getOptionValue("sync");
-				checkMandatoryParameter(licFilename, "sync");
+				String licFilename = cmd.getOptionValue("renew");
+				checkMandatoryParameter(licFilename, "renew");
 				String server = cmd.getOptionValue("server");
 				checkMandatoryParameter(server, "server");
 
@@ -176,7 +176,7 @@
 		options.addOption(OptionBuilder.withArgName("lic_file").withLongOpt("validate").withDescription("Validate lic file.").hasArg(true).create('l'));
 
 		options.addOption("g", "gen_request", false, "Generate request file. If --rfile parameter is missing then It is generated in current directory.");
-		options.addOption("c", "create", false, "Request a license file from server. --rfile and --server parameters are mandatory.");
+		options.addOption(OptionBuilder.withArgName("lic_file").withLongOpt("create").withDescription("Request a license file from server. --server parameters is mandatory.").hasArg(true).create('c'));
 		options.addOption("t", "test_lc", false, "Test if License Server (LC) is available. --server parameter is mandatory.");
 		options.addOption(OptionBuilder.withArgName("lic_file").withLongOpt("renew").withDescription("Synchronize/renew the current license file. --server parameter is mandatory.").hasArg(true).create('r'));
 
diff --git a/src/main/java/net/curisit/securis/LicenseManager.java b/src/main/java/net/curisit/securis/LicenseManager.java
index d3e7f16..83571f0 100644
--- a/src/main/java/net/curisit/securis/LicenseManager.java
+++ b/src/main/java/net/curisit/securis/LicenseManager.java
@@ -2,20 +2,30 @@
 
 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 net.curisit.securis.beans.LicenseBean;
 import net.curisit.securis.beans.RequestBean;
+import net.curisit.securis.beans.SignedLicenseBean;
 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, sync, requesting, ...
+ * Manage all licenses tasks, just like validation, renew, requesting, ...
  * 
  * @author roberto <roberto.sanchez@curisit.net>
  */
 public class LicenseManager {
+
+	private static final Logger log = LogManager.getLogger(License.class);
 
 	private static LicenseManager singleton = new LicenseManager();
 
@@ -24,6 +34,23 @@
 
 	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;
 	}
 
 	/**
@@ -42,17 +69,56 @@
 	 * @throws SeCurisException
 	 */
 	public LicenseBean validateLicense(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);
-		}
+		LicenseBean licBean = load(licFile);
 		SignatureHelper.getInstance().validateSignature(licBean);
 		LicenseValidator.getInstance().validateHW(licBean, Params.get(Params.KEYS.APPLICATION_CODE), Params.get(Params.KEYS.CUSTOMER_CODE));
 		LicenseValidator.getInstance().validateLogo(licBean);
 
 		return licBean;
+	}
+
+	/**
+	 * Request to server for a valid license
+	 * 
+	 * @return The license bean returned by the server
+	 * @throws SeCurisException
+	 */
+	public LicenseBean requestLicense() throws SeCurisException {
+		RequestBean req = ReqGenerator.getInstance().createRequest(Params.get(Params.KEYS.APPLICATION_CODE), Params.get(Params.KEYS.CUSTOMER_CODE));
+		if (true)
+			throw new SeCurisException("Action not implemented yet");
+		LicenseBean lic = requestLicenseToServer(req);
+		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);
+		byte[] json;
+		try {
+			json = JsonUtils.toJSON(signedLic, true).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: " + license, e);
+			throw new SeCurisException("Error creating json doc from license: " + license, e);
+		} catch (IOException e) {
+			log.error("Error creating license file: " + file, e);
+			throw new SeCurisException("Error creating json doc from license: " + license, e);
+		}
+
+		log.debug("License saved in {}", file);
+
+	}
+
+	private LicenseBean requestLicenseToServer(RequestBean req) {
+		// TODO Prepare call to server sending the request bean to get a valid license
+		return null;
 	}
 
 	/**
@@ -79,7 +145,7 @@
 	 * @return New license bean if server creates a new one, otherwise the same current License bean will be returned
 	 * @throws SeCurisException
 	 */
-	public LicenseBean sync(File licenseFile) throws SeCurisException {
+	public LicenseBean renew(File licenseFile) throws SeCurisException {
 		LicenseBean lic = validateLicense(licenseFile);
 		if (true)
 			throw new SeCurisException("Action not implemented yet");
diff --git a/src/main/java/net/curisit/securis/ReqGenerator.java b/src/main/java/net/curisit/securis/ReqGenerator.java
index 3aecc16..15c86f8 100644
--- a/src/main/java/net/curisit/securis/ReqGenerator.java
+++ b/src/main/java/net/curisit/securis/ReqGenerator.java
@@ -9,6 +9,7 @@
 import java.nio.file.StandardOpenOption;
 
 import net.curisit.securis.beans.RequestBean;
+import net.curisit.securis.utils.HWInfo;
 import net.curisit.securis.utils.JsonUtils;
 import net.curisit.securis.utils.LicUtils;
 
diff --git a/src/patch/java/net/curisit/securis/beans/SignedLicenseBean.java b/src/main/java/net/curisit/securis/beans/SignedLicenseBean.java
similarity index 100%
rename from src/patch/java/net/curisit/securis/beans/SignedLicenseBean.java
rename to src/main/java/net/curisit/securis/beans/SignedLicenseBean.java
diff --git a/src/main/java/net/curisit/securis/utils/SignatureHelper.java b/src/main/java/net/curisit/securis/utils/SignatureHelper.java
index dbe03a6..8618b97 100644
--- a/src/main/java/net/curisit/securis/utils/SignatureHelper.java
+++ b/src/main/java/net/curisit/securis/utils/SignatureHelper.java
@@ -36,7 +36,7 @@
 	private static SignatureHelper singleton = new SignatureHelper();
 
 	private static final String DEFAULT_ALGORITHM = "RSA";
-	protected static final String SIGNATURE_GENERATION_ALGORITHM = "SHA256withRSA";
+	public static final String SIGNATURE_GENERATION_ALGORITHM = "SHA256withRSA";
 
 	private SignatureHelper() {
 	}
@@ -45,7 +45,7 @@
 		return singleton;
 	}
 
-	protected void prepareSignature(Signature signature, LicenseBean licBean) throws SeCurisException {
+	public void prepareSignature(Signature signature, LicenseBean licBean) throws SeCurisException {
 		try {
 			log.info("JSON: {}", JsonUtils.toJSON(licBean));
 			signature.update(JsonUtils.toJSON(licBean).getBytes("utf-8"));
@@ -98,7 +98,7 @@
 		return publicKey;
 	}
 
-	protected PrivateKey generatePrivateKey(File privateKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
+	public PrivateKey generatePrivateKey(File privateKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
 		String privKeyBase64 = FileUtils.readFileToString(privateKeyFile);
 		int from = privKeyBase64.indexOf('\n');
 		int to = privKeyBase64.indexOf("-----END", from);
@@ -111,7 +111,7 @@
 		return privateKey;
 	}
 
-	private KeyPair generateKeyPair(File privateKeyFile, File publicKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
+	public KeyPair generateKeyPair(File privateKeyFile, File publicKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
 
 		PublicKey publicKey = generatePublicKey(publicKeyFile);
 		PrivateKey privateKey = generatePrivateKey(privateKeyFile);
diff --git a/src/patch/java/net/curisit/securis/LicenseGenerator.java b/src/patch/java/net/curisit/securis/LicenseGenerator.java
index f84f980..493a2d1 100644
--- a/src/patch/java/net/curisit/securis/LicenseGenerator.java
+++ b/src/patch/java/net/curisit/securis/LicenseGenerator.java
@@ -20,6 +20,7 @@
 import net.curisit.securis.beans.RequestBean;
 import net.curisit.securis.beans.SignedLicenseBean;
 import net.curisit.securis.utils.JsonUtils;
+import net.curisit.securis.utils.SignatureHelper;
 
 import org.apache.commons.net.util.Base64;
 import org.apache.logging.log4j.LogManager;

--
Gitblit v1.3.2