Roberto Sánchez
2014-02-25 bc372a688bf2062ba1e7e2ef2f9e69123d7873db
#593 doc - Added HOW-TO doc
1 files added
6 files modified
1 files renamed
changed files
.gitignore patch | view | blame | history
etc/build/files/README.md patch | view | blame | history
src/main/java/net/curisit/securis/License.java patch | view | blame | history
src/main/java/net/curisit/securis/LicenseManager.java patch | view | blame | history
src/main/java/net/curisit/securis/ReqGenerator.java patch | view | blame | history
src/main/java/net/curisit/securis/beans/SignedLicenseBean.java patch | view | blame | history
src/main/java/net/curisit/securis/utils/SignatureHelper.java patch | view | blame | history
src/patch/java/net/curisit/securis/LicenseGenerator.java patch | view | blame | history
.gitignore
....@@ -3,3 +3,4 @@
33 /.settings
44 /.classpath
55 /.project
6
+/doc/javadoc
etc/build/files/README.md
....@@ -0,0 +1,185 @@
1
+#SeCuris client
2
+
3
+##Usage securis-cient API
4
+
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.pub
26
+app.code = AP01
27
+customer.code = XX
28
+```
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 administrator
32
+* ```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 mandatory
35
+
36
+### Validate license file
37
+
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 license
57
+
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 license
74
+
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 CLI
98
+
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/bash
105
+export CLASSPATH=libs/*.jar
106
+java -cp $CLASSPATH -jar libs/securis-client-*.jar $@
107
+```
108
+
109
+
110
+### Creation of a request file
111
+
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.req
116
+
117
+```
118
+
119
+### Validate license file
120
+
121
+```
122
+ $ ./securis.sh --validate=/path/to/license/file/curisapp.lic
123
+
124
+```
125
+
126
+### Request a new license to server
127
+
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 license
134
+
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 files
141
+
142
+The request and license file are json files and the content can be read easily
143
+
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" : 23
173
+ },
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 @@
103103 }
104104
105105 if (cmd.hasOption('r')) {
106
- String licFilename = cmd.getOptionValue("sync");
107
- checkMandatoryParameter(licFilename, "sync");
106
+ String licFilename = cmd.getOptionValue("renew");
107
+ checkMandatoryParameter(licFilename, "renew");
108108 String server = cmd.getOptionValue("server");
109109 checkMandatoryParameter(server, "server");
110110
....@@ -176,7 +176,7 @@
176176 options.addOption(OptionBuilder.withArgName("lic_file").withLongOpt("validate").withDescription("Validate lic file.").hasArg(true).create('l'));
177177
178178 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'));
180180 options.addOption("t", "test_lc", false, "Test if License Server (LC) is available. --server parameter is mandatory.");
181181 options.addOption(OptionBuilder.withArgName("lic_file").withLongOpt("renew").withDescription("Synchronize/renew the current license file. --server parameter is mandatory.").hasArg(true).create('r'));
182182
src/main/java/net/curisit/securis/LicenseManager.java
....@@ -2,20 +2,30 @@
22
33 import java.io.File;
44 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;
59
610 import net.curisit.securis.beans.LicenseBean;
711 import net.curisit.securis.beans.RequestBean;
12
+import net.curisit.securis.beans.SignedLicenseBean;
813 import net.curisit.securis.utils.JsonUtils;
914 import net.curisit.securis.utils.Params;
15
+import net.curisit.securis.utils.SignatureHelper;
1016
1117 import org.apache.commons.io.FileUtils;
18
+import org.apache.logging.log4j.LogManager;
19
+import org.apache.logging.log4j.Logger;
1220
1321 /**
14
- * Manage all licenses tasks, just like, validation, sync, requesting, ...
22
+ * Manage all licenses tasks, just like validation, renew, requesting, ...
1523 *
1624 * @author roberto <roberto.sanchez@curisit.net>
1725 */
1826 public class LicenseManager {
27
+
28
+ private static final Logger log = LogManager.getLogger(License.class);
1929
2030 private static LicenseManager singleton = new LicenseManager();
2131
....@@ -24,6 +34,23 @@
2434
2535 public static LicenseManager getInstance() {
2636 return singleton;
37
+ }
38
+
39
+ /**
40
+ * Loads a license from file
41
+ *
42
+ * @param licFile
43
+ * @return The license bean
44
+ * @throws SeCurisException
45
+ */
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;
2754 }
2855
2956 /**
....@@ -42,17 +69,56 @@
4269 * @throws SeCurisException
4370 */
4471 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);
5173 SignatureHelper.getInstance().validateSignature(licBean);
5274 LicenseValidator.getInstance().validateHW(licBean, Params.get(Params.KEYS.APPLICATION_CODE), Params.get(Params.KEYS.CUSTOMER_CODE));
5375 LicenseValidator.getInstance().validateLogo(licBean);
5476
5577 return licBean;
78
+ }
79
+
80
+ /**
81
+ * Request to server for a valid license
82
+ *
83
+ * @return The license bean returned by the server
84
+ * @throws SeCurisException
85
+ */
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 license
98
+ * @param file
99
+ * @throws SeCurisException
100
+ */
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 license
121
+ return null;
56122 }
57123
58124 /**
....@@ -79,7 +145,7 @@
79145 * @return New license bean if server creates a new one, otherwise the same current License bean will be returned
80146 * @throws SeCurisException
81147 */
82
- public LicenseBean sync(File licenseFile) throws SeCurisException {
148
+ public LicenseBean renew(File licenseFile) throws SeCurisException {
83149 LicenseBean lic = validateLicense(licenseFile);
84150 if (true)
85151 throw new SeCurisException("Action not implemented yet");
src/main/java/net/curisit/securis/ReqGenerator.java
....@@ -9,6 +9,7 @@
99 import java.nio.file.StandardOpenOption;
1010
1111 import net.curisit.securis.beans.RequestBean;
12
+import net.curisit.securis.utils.HWInfo;
1213 import net.curisit.securis.utils.JsonUtils;
1314 import net.curisit.securis.utils.LicUtils;
1415
src/patch/java/net/curisit/securis/beans/SignedLicenseBean.java
similarity 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 @@
3636 private static SignatureHelper singleton = new SignatureHelper();
3737
3838 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";
4040
4141 private SignatureHelper() {
4242 }
....@@ -45,7 +45,7 @@
4545 return singleton;
4646 }
4747
48
- protected void prepareSignature(Signature signature, LicenseBean licBean) throws SeCurisException {
48
+ public void prepareSignature(Signature signature, LicenseBean licBean) throws SeCurisException {
4949 try {
5050 log.info("JSON: {}", JsonUtils.toJSON(licBean));
5151 signature.update(JsonUtils.toJSON(licBean).getBytes("utf-8"));
....@@ -98,7 +98,7 @@
9898 return publicKey;
9999 }
100100
101
- protected PrivateKey generatePrivateKey(File privateKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
101
+ public PrivateKey generatePrivateKey(File privateKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
102102 String privKeyBase64 = FileUtils.readFileToString(privateKeyFile);
103103 int from = privKeyBase64.indexOf('\n');
104104 int to = privKeyBase64.indexOf("-----END", from);
....@@ -111,7 +111,7 @@
111111 return privateKey;
112112 }
113113
114
- private KeyPair generateKeyPair(File privateKeyFile, File publicKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
114
+ public KeyPair generateKeyPair(File privateKeyFile, File publicKeyFile) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
115115
116116 PublicKey publicKey = generatePublicKey(publicKeyFile);
117117 PrivateKey privateKey = generatePrivateKey(privateKeyFile);
src/patch/java/net/curisit/securis/LicenseGenerator.java
....@@ -20,6 +20,7 @@
2020 import net.curisit.securis.beans.RequestBean;
2121 import net.curisit.securis.beans.SignedLicenseBean;
2222 import net.curisit.securis.utils.JsonUtils;
23
+import net.curisit.securis.utils.SignatureHelper;
2324
2425 import org.apache.commons.net.util.Base64;
2526 import org.apache.logging.log4j.LogManager;