Skip to content

Commit 8091110

Browse files
author
Luigi Zuccarelli
committed
Added JNDI keystore support for key pairs
1 parent 084ce85 commit 8091110

18 files changed

+112
-22
lines changed

README.md

+3-7
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,7 @@ The folder test-keystore is used for testing and should not be used for any prod
3636

3737
```
3838
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"controller":"com.microlib.controller.JwtService" , "action":"getToken"}' http://localhost:9000
39-
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"controller":"com.microlib.controller.JwtService" , "action":"createAndSignToken", "key-id":"test-keystore"}' http://localhost:9000
40-
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"controller":"com.microlib.controller.JwtService" , "action":"verifyToken", "key-id":"test-keystore" , "token": "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.gF-JDds389H5l4tk2o7qpuSIzSAEgjfVwTb7c3Tf1InuD7EWk5gjY4kKPP__MGc39HfOobjqUMsUFAJBAJYOJxKmfLMBCLr5TXMMeLcc3-qZw3NZ0DDhq76yLiVA_P3pBm1k-kKtZQvwRY8VrLN9JfBm0BDy3f2wvNRmDXQLHAU33fi4zACpGcTJ9TfNBoY84sOGUBhd73yxPLr4lBhYrFjcqGboZDNzg2LdisTVP1I_9KlHA4d8-H5LHYOcwiFD-hFZteKl52jslKfNucHgrhn0D1iLf4YiE92yNVobLAkVN_qPG8ZX8sNlA5AahIqKenk6hK_C0f1LTGzc6ZxXMA"}' http://localhost:9000
39+
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"controller":"com.microlib.controller.JwtService" , "action":"createAndSignToken", "key-id":"test"}' http://localhost:9000
40+
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"controller":"com.microlib.controller.JwtService" , "action":"verifyToken", "key-id":"test" , "token": "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.gF-JDds389H5l4tk2o7qpuSIzSAEgjfVwTb7c3Tf1InuD7EWk5gjY4kKPP__MGc39HfOobjqUMsUFAJBAJYOJxKmfLMBCLr5TXMMeLcc3-qZw3NZ0DDhq76yLiVA_P3pBm1k-kKtZQvwRY8VrLN9JfBm0BDy3f2wvNRmDXQLHAU33fi4zACpGcTJ9TfNBoY84sOGUBhd73yxPLr4lBhYrFjcqGboZDNzg2LdisTVP1I_9KlHA4d8-H5LHYOcwiFD-hFZteKl52jslKfNucHgrhn0D1iLf4YiE92yNVobLAkVN_qPG8ZX8sNlA5AahIqKenk6hK_C0f1LTGzc6ZxXMA"}' http://localhost:9000
4141
42-
```
43-
44-
## Improvements
45-
46-
Read all key pairs into memory at server startup
42+
```
File renamed without changes.
File renamed without changes.

app-keystore/mongodb/private_key.der

1.19 KB
Binary file not shown.

app-keystore/mongodb/public_key.der

294 Bytes
Binary file not shown.
File renamed without changes.
File renamed without changes.

app-keystore/test/private_key.der

1.19 KB
Binary file not shown.
File renamed without changes.

app-keystore/test/public_key.der

294 Bytes
Binary file not shown.
1.19 KB
Binary file not shown.
294 Bytes
Binary file not shown.

make.sh

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,24 @@ function usage() {
2626
function clean() {
2727
rm -rf classes/com/*
2828
echo "Task : [clean] completed"
29-
echo " "
29+
echo " "
3030
}
3131

3232
function compile() {
33-
find src/ -name \*.java -print > file.list
33+
find src/ -name \*.java -print > file.list
3434
javac -g -d classes -cp $CP @file.list
3535
echo "Task : [compile] completed"
3636
cp src/com/microlib/server/*.properties classes/com/microlib/server/
3737
cp src/com/microlib/jndi/service/*.properties classes/com/microlib/jndi/service/
3838
cp src/*.properties classes/
3939
echo "Task : [copying resources] completed"
40-
echo " "
40+
echo " "
4141
}
4242

4343
function run() {
4444
java -cp $CP com.microlib.server.TheServer 9000 100
4545
echo "Task : [run] completed"
46-
echo " "
46+
echo " "
4747
}
4848

4949

src/com/microlib/controller/JwtService.java

+23-8
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,30 @@
33
import com.auth0.jwt.*;
44
import com.auth0.jwt.algorithms.*;
55
import com.auth0.jwt.exceptions.*;
6-
import java.nio.file.*;
7-
import java.io.*;
86
import java.security.*;
97
import java.security.spec.*;
108
import java.security.interfaces.*;
119
import org.apache.commons.logging.*;
1210
import org.apache.commons.logging.impl.*;
13-
import java.util.Map;
1411
import java.util.List;
12+
import java.util.Map;
13+
import java.util.Hashtable;
14+
import javax.naming.Context;
15+
import javax.naming.InitialContext;
1516
import com.microlib.dataformat.*;
17+
import com.microlib.jndi.service.*;
18+
import java.io.UnsupportedEncodingException;
19+
import javax.naming.NamingException;
1620

1721
public class JwtService implements ExecInterface {
1822

1923
int nLoop = 0;
2024
private boolean bRunning = false;
2125
private String name;
2226
private static org.apache.commons.logging.Log log;
27+
final static String jndiName = "java/KeyStore";
28+
private KeyPairStoreImpl keyStore;
29+
2330

2431
public boolean isRunning() {
2532
return bRunning;
@@ -58,15 +65,15 @@ public String doProcess(Map<String, Object> map) {
5865
if (null == map.get("key-id")) {
5966
response = json.message("ERROR no key-id found ", "KO");
6067
} else {
61-
byte[] keyBytes = Files.readAllBytes(new File(map.get("key-id").toString() + "/private_key.der").toPath());
68+
byte[] keyBytes = keyStore.getPrivateByteArray(map.get("key-id").toString());
6269
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
6370
KeyFactory kf = KeyFactory.getInstance("RSA");
6471
RSAPrivateKey key = (RSAPrivateKey) kf.generatePrivate(spec);
6572
String token = JWT.create().withIssuer("auth0").sign(Algorithm.RSA256(key));
6673
log.info("Signed Token : " + token);
6774
response = json.message("Signed Token " + token, "OK");
6875
}
69-
} catch (JWTCreationException | IOException | NoSuchAlgorithmException | InvalidKeySpecException exception) {
76+
} catch (JWTCreationException | NoSuchAlgorithmException | InvalidKeySpecException exception) {
7077
log.error(exception);
7178
response = json.message("ERROR " + exception.toString(), "KO");
7279
}
@@ -75,7 +82,7 @@ public String doProcess(Map<String, Object> map) {
7582
if (null == map.get("key-id")) {
7683
response = json.message("ERROR no key-id found ", "KO");
7784
} else {
78-
byte[] keyBytes = Files.readAllBytes(new File(map.get("key-id").toString() + "/public_key.der").toPath());
85+
byte[] keyBytes = keyStore.getPublicByteArray(map.get("key-id").toString());
7986
X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
8087
KeyFactory kf = KeyFactory.getInstance("RSA");
8188
RSAPublicKey key = (RSAPublicKey) kf.generatePublic(spec);
@@ -85,7 +92,7 @@ public String doProcess(Map<String, Object> map) {
8592
log.info("Token verified " + jwt);
8693
response = json.message("Token verified ", "OK");
8794
}
88-
} catch (JWTVerificationException | JWTCreationException | IOException | NoSuchAlgorithmException
95+
} catch (JWTVerificationException | JWTCreationException | NoSuchAlgorithmException
8996
| InvalidKeySpecException exception) {
9097
log.error(exception);
9198
response = json.message("ERROR " + exception.toString(), "KO");
@@ -97,6 +104,14 @@ public String doProcess(Map<String, Object> map) {
97104
}
98105

99106
public void init(String sIn) {
100-
log = LogFactory.getLog(JwtService.class);
107+
try {
108+
log = LogFactory.getLog(JwtService.class);
109+
Hashtable<String, String> ht = new Hashtable<String, String>();
110+
ht.put("java.naming.factory.initial", "com.microlib.jndi.DSInitCtxFactory");
111+
Context ctx = new InitialContext(ht);
112+
keyStore = (KeyPairStoreImpl) ctx.lookup(jndiName);
113+
} catch(NamingException e) {
114+
// we can't assume that the log is available
115+
}
101116
}
102117
}

src/com/microlib/jndi/service/JndiInterface.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* @author: Luigi Mario Zuccarelli
99
* @version: 1.10
1010
* @date: Generated on Mon Dec 29 15:30:20 CEST 2014
11-
* @file: PluginInterface.java
11+
* @file: JndiInterface.java
1212
*
1313
*/
1414

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.microlib.jndi.service;
2+
3+
4+
import org.apache.commons.logging.*;
5+
import org.apache.commons.logging.impl.*;
6+
import java.util.*;
7+
import java.nio.file.*;
8+
import java.io.*;
9+
10+
/**
11+
* @(#) BasicDataSourceImpl
12+
*
13+
* In the light of open source software you are free to do what you like with this code.
14+
* Redistribution and use in source and binary forms, with or without
15+
* modification, is absolutely permitted - just keep the credits please.
16+
*
17+
* @author: Luigi Mario Zuccarelli
18+
* @version: 1.10
19+
* @date: Generated on Mon Dec 29 15:30:20 CEST 2014
20+
* @file: BasicDataSourceImpl.java
21+
*
22+
*
23+
*
24+
* Tags for CVS
25+
* $Author$
26+
* $Id$
27+
* $Date$
28+
*
29+
*/
30+
31+
public class KeyPairStoreImpl implements JndiInterface {
32+
33+
private static org.apache.commons.logging.Log log;
34+
private Map<String, byte[]> publicKeyStore = new HashMap<String, byte[]>();
35+
private Map<String, byte[]> privateKeyStore = new HashMap<String, byte[]>();
36+
37+
public KeyPairStoreImpl() {
38+
log = LogFactory.getLog(KeyPairStoreImpl.class);
39+
}
40+
41+
public void init(String sIn) {
42+
43+
try {
44+
File[] directories = new File("app-keystore").listFiles(File::isDirectory);
45+
for (File f : directories) {
46+
log.info("Loading keypair for " + f.getName());
47+
privateKeyStore.put(f.getName(), Files.readAllBytes(new File(f.getPath() + "/private_key.der").toPath()));
48+
publicKeyStore.put(f.getName(), Files.readAllBytes(new File(f.getPath() + "/public_key.der").toPath()));
49+
}
50+
} catch (IOException io) {
51+
log.error(io);
52+
}
53+
}
54+
55+
public byte[] getPrivateByteArray(String sIn) {
56+
return privateKeyStore.get(sIn);
57+
}
58+
59+
public byte[] getPublicByteArray(String sIn) {
60+
return publicKeyStore.get(sIn);
61+
}
62+
63+
public void destroy() {
64+
try {
65+
log.info(" ");
66+
privateKeyStore = null;
67+
publicKeyStore = null;
68+
} catch (Exception e) {
69+
log.error(e);
70+
} finally {
71+
log = null;
72+
}
73+
}
74+
}

src/com/microlib/server/TheServer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public TheServer(int port, int threads) {
9393
log.info(" ");
9494
log.info("Press CTRL-C to gracefully shutdown the server ");
9595
log.info(" ");
96+
log.info(" ");
9697

9798
while (!bStop) {
9899
Socket socket = listener.accept();
@@ -128,5 +129,4 @@ public void run() {
128129
}
129130
}
130131
}
131-
132132
}

src/com/microlib/server/TheServer.properties

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
# plugins [service list]
66

7-
jndiplugin.count=11
7+
jndiplugin.count=12
88

99
# BasicDataSourceImpl
1010
name.0=com.microlib.jndi.service.BasicDataSourceImpl
@@ -71,3 +71,8 @@ use.10=true
7171
value.10=0
7272
jndi.10=java/Scheduler
7373

74+
# KeyPairStoreImpl
75+
name.11=com.microlib.jndi.service.KeyPairStoreImpl
76+
use.11=true
77+
value.11=0
78+
jndi.11=java/KeyStore

0 commit comments

Comments
 (0)