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