m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagdalena Grodzińska <mag.grodzinska@gmail.com>2020-01-12 21:05:28 +0100
committerMagdalena Grodzińska <mag.grodzinska@gmail.com>2020-01-12 21:05:28 +0100
commitda5df3957ba41d28256ab8183aae0dd3b6e0dcba (patch)
tree285a927acfcac8928f453215d9c6817de2a9c5af
parentead50cfbb310feaaf6dfc7da6b59165428e4833a (diff)
Add query signer architecture
-rw-r--r--build.gradle12
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementation.java4
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java4
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/api/Api.java4
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java31
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/model/ValueQuery.java22
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySigner.java26
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySignerApiImplementation.java112
-rw-r--r--src/main/java/pl/edu/mimuw/cloudatlas/querysignerapi/QuerySignerApi.java17
9 files changed, 215 insertions, 17 deletions
diff --git a/build.gradle b/build.gradle
index d7909f7..c557cad 100644
--- a/build.gradle
+++ b/build.gradle
@@ -46,6 +46,10 @@ ext.UDUPServerBufsize = {
return System.getProperty("bufsize") ?: 512;
}
+ext.querySignerHostname = {
+ return System.getProperty("querySignerHostname") ?: "localhost"
+}
+
/*
Possible options:
RoundRobinExp
@@ -110,6 +114,7 @@ task runAgent(type: JavaExec) {
systemProperty 'UDUPServer.bufsize', UDUPServerBufsize()
systemProperty 'Gossip.zone_strategy', zoneSelectionStrategy()
systemProperty 'zone_path', zonePath()
+ systemProperty 'query_signer_hostname', querySignerHostname()
}
task runClient(type: JavaExec) {
@@ -117,6 +122,7 @@ task runClient(type: JavaExec) {
main = 'pl.edu.mimuw.cloudatlas.client.Client'
systemProperty 'agent_hostname', hostname()
systemProperty 'zone_path', zonePath()
+ systemProperty 'query_signer_hostname', querySignerHostname()
}
task runFetcher(type: JavaExec) {
@@ -131,3 +137,9 @@ task runInterpreter(type: JavaExec) {
main = 'pl.edu.mimuw.cloudatlas.interpreter.Main'
standardInput = System.in
}
+
+task runQuerySigner(type: JavaExec) {
+ classpath = sourceSets.main.runtimeClasspath
+ main = 'pl.edu.mimuw.cloudatlas.querysigner.QuerySigner'
+ systemProperty 'query_signer_hostname', querySignerHostname()
+}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementation.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementation.java
index d2e808a..fe3136d 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementation.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/ApiImplementation.java
@@ -60,7 +60,7 @@ public class ApiImplementation implements Api {
}
}
- public void installQuery(String name, String queryCode) throws RemoteException {
+ public void installQuery(String name, String queryCode, byte[] querySignature) throws RemoteException {
Pattern queryNamePattern = Pattern.compile("&[a-zA-Z][\\w_]*");
Matcher matcher = queryNamePattern.matcher(name);
if (!matcher.matches()) {
@@ -85,7 +85,7 @@ public class ApiImplementation implements Api {
}
}
- public void uninstallQuery(String queryName) throws RemoteException {
+ public void uninstallQuery(String queryName, byte[] querySignature) throws RemoteException {
uninstallQueryInHierarchy(root, new Attribute(queryName));
}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java b/src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java
index b293446..450382d 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/agent/NewApiImplementation.java
@@ -79,7 +79,7 @@ public class NewApiImplementation implements Api {
}
}
- public void installQuery(String name, String queryCode) throws RemoteException {
+ public void installQuery(String name, String queryCode, byte[] querySignature) throws RemoteException {
Pattern queryNamePattern = Pattern.compile("&[a-zA-Z][\\w_]*");
Matcher matcher = queryNamePattern.matcher(name);
if (!matcher.matches()) {
@@ -98,7 +98,7 @@ public class NewApiImplementation implements Api {
}
}
- public void uninstallQuery(String queryName) throws RemoteException {
+ public void uninstallQuery(String queryName, byte[] querySignature) throws RemoteException {
try {
Attribute attributeName = new Attribute(queryName);
ValueTime timestamp = new ValueTime(System.currentTimeMillis());
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/api/Api.java b/src/main/java/pl/edu/mimuw/cloudatlas/api/Api.java
index c62ee39..63c7f54 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/api/Api.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/api/Api.java
@@ -27,9 +27,9 @@ public interface Api extends Remote {
public AttributesMap getZoneAttributeValues(String zoneName) throws RemoteException;
- public void installQuery(String queryName, String query) throws RemoteException;
+ public void installQuery(String queryName, String query, byte[] querySignature) throws RemoteException;
- public void uninstallQuery(String queryName) throws RemoteException;
+ public void uninstallQuery(String queryName, byte[] querySignature) throws RemoteException;
public void setAttributeValue(String zoneName, String attributeName, Value value) throws RemoteException;
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java b/src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java
index 4019696..14f531e 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/client/ClientController.java
@@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import pl.edu.mimuw.cloudatlas.api.Api;
import pl.edu.mimuw.cloudatlas.model.*;
+import pl.edu.mimuw.cloudatlas.querysignerapi.QuerySignerApi;
import java.net.InetAddress;
import java.rmi.registry.LocateRegistry;
@@ -32,17 +33,22 @@ import java.util.*;
@Controller
public class ClientController {
- private Api api;
-
+ private Api agentApi;
+ private QuerySignerApi querySignerApi;
+ private Map<String, byte[]> querySignatures;
private Map<ValueTime, AttributesMap> attributes;
private String currentZoneName;
private static final int MAX_ENTRIES = 10;
ClientController() {
try {
- String hostname = System.getProperty("agent_hostname");
- Registry registry = LocateRegistry.getRegistry(hostname);
- this.api = (Api) registry.lookup("Api");
+ String agentHostname = System.getProperty("agent_hostname");
+ Registry registry = LocateRegistry.getRegistry(agentHostname);
+ this.agentApi = (Api) registry.lookup("Api");
+
+ String querySignerHostname = System.getProperty("querysigner_hostname");
+ Registry querySignerRegistry = LocateRegistry.getRegistry(querySignerHostname);
+ this.querySignerApi = (QuerySignerApi) querySignerRegistry.lookup("QuerySignerApi");
} catch (Exception e) {
System.err.println("Client exception:");
e.printStackTrace();
@@ -54,6 +60,7 @@ public class ClientController {
}
};
this.currentZoneName = System.getProperty("zone_path");
+ this.querySignatures = new HashMap<>();
fetchAttributeData(); // fetch attribute data as early as possible
}
@@ -74,7 +81,9 @@ public class ClientController {
boolean success = true;
try {
- this.api.installQuery(queryObject.getName(), queryObject.getValue());
+ byte[] querySignature = this.querySignerApi.signQuery(queryObject.getName(), queryObject.getValue());
+ querySignatures.put(queryObject.getName(), querySignature);
+ this.agentApi.installQuery(queryObject.getName(), queryObject.getValue(), querySignature);
} catch (Exception e) {
success = false;
System.err.println("Client exception:");
@@ -99,7 +108,7 @@ public class ClientController {
boolean success = true;
try {
- this.api.uninstallQuery(queryObject.getName());
+ this.agentApi.uninstallQuery(queryObject.getName(), querySignatures.get(queryObject.getName()));
} catch (Exception e) {
success = false;
System.err.println("Client exception:");
@@ -153,7 +162,7 @@ public class ClientController {
try {
contactObjects = parseContactsString(contactsObject);
- this.api.setFallbackContacts(contactObjects);
+ this.agentApi.setFallbackContacts(contactObjects);
} catch (Exception e) {
success = false;
System.err.println("Client exception:");
@@ -284,7 +293,7 @@ public class ClientController {
try {
attributeValue = parseAttributeValue(attributeObject);
- api.setAttributeValue(
+ agentApi.setAttributeValue(
attributeObject.getZoneName(),
attributeObject.getAttributeName(),
attributeValue);
@@ -309,7 +318,7 @@ public class ClientController {
String availableZonesString = "";
try {
- availableZones = api.getZoneSet();
+ availableZones = agentApi.getZoneSet();
availableZonesString = availableZones.toString().substring(1, availableZones.toString().length() - 1);
} catch (Exception e) {
success = false;
@@ -336,7 +345,7 @@ public class ClientController {
try {
if (!this.currentZoneName.isEmpty()) {
- attribData = api.getZoneAttributeValues(this.currentZoneName);
+ attribData = agentApi.getZoneAttributeValues(this.currentZoneName);
currentTime = new ValueTime(System.currentTimeMillis());
this.attributes.put(currentTime, attribData);
}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/model/ValueQuery.java b/src/main/java/pl/edu/mimuw/cloudatlas/model/ValueQuery.java
index 82e1602..d203e99 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/model/ValueQuery.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/model/ValueQuery.java
@@ -15,6 +15,28 @@ public class ValueQuery extends Value {
private String code;
// Parsed query
private Program query;
+
+ public byte[] getSignature() {
+ return signature;
+ }
+
+ public void setSignature(byte[] signature) {
+ this.signature = signature;
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ // Query signature
+ private byte[] signature;
+ // Query signing timestamp
+ private long timestamp;
+
/**
* Constructs a new <code>ValueQuery</code> object.
*
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySigner.java b/src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySigner.java
index e5e561d..69a25d7 100644
--- a/src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySigner.java
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySigner.java
@@ -1,4 +1,30 @@
package pl.edu.mimuw.cloudatlas.querysigner;
+import pl.edu.mimuw.cloudatlas.agent.EventBus;
+import pl.edu.mimuw.cloudatlas.api.Api;
+import pl.edu.mimuw.cloudatlas.querysignerapi.QuerySignerApi;
+
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+
public class QuerySigner {
+
+ public static void runRegistry() {
+ try {
+ QuerySignerApiImplementation api = new QuerySignerApiImplementation();
+ QuerySignerApi apiStub =
+ (QuerySignerApi) UnicastRemoteObject.exportObject(api, 0);
+ Registry registry = LocateRegistry.getRegistry();
+ registry.rebind("QuerySignerApi", apiStub);
+ System.out.println("QuerySigner: api bound");
+ } catch (Exception e) {
+ System.err.println("QuerySigner registry initialization exception:");
+ e.printStackTrace();
+ }
+ }
+
+ public static void main(String[] args) {
+ runRegistry();
+ }
}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySignerApiImplementation.java b/src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySignerApiImplementation.java
new file mode 100644
index 0000000..38a86c6
--- /dev/null
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/querysigner/QuerySignerApiImplementation.java
@@ -0,0 +1,112 @@
+package pl.edu.mimuw.cloudatlas.querysigner;
+
+import pl.edu.mimuw.cloudatlas.model.ValueQuery;
+import pl.edu.mimuw.cloudatlas.querysignerapi.QuerySignerApi;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.rmi.RemoteException;
+import java.security.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class QuerySignerApiImplementation implements QuerySignerApi {
+ private PublicKey publicKey;
+ private PrivateKey privateKey;
+ private final static String ENCRYPTION_ALGORITHM = "RSA";
+ private final static int NUM_KEY_BITS = 1024;
+ private Map<String, ValueQuery> queries;
+ private Set<String> attribsSetByQueries;
+
+ QuerySignerApiImplementation() {
+ this.queries = new HashMap<>();
+ this.attribsSetByQueries = new HashSet<>();
+ try {
+ generateKeys();
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private String byteArrayToString(byte[] arr, int offset, int len) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = offset, n = Math.min(arr.length, offset + len); i < n; ++i) {
+ String hex = Integer.toHexString(0xFF & arr[i]);
+ if (hex.length() < 2) {
+ sb.append('0');
+ }
+ sb.append(hex);
+ }
+ return sb.toString();
+ }
+
+ private void generateKeys() throws NoSuchAlgorithmException {
+ KeyPairGenerator keyGenerator =
+ KeyPairGenerator.getInstance(ENCRYPTION_ALGORITHM);
+ keyGenerator.initialize(NUM_KEY_BITS);
+ KeyPair keyPair = keyGenerator.generateKeyPair();
+ this.privateKey = keyPair.getPrivate();
+ this.publicKey = keyPair.getPublic();
+ }
+
+ private byte[] encryptQuery(String query) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+ Cipher signCipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
+ signCipher.init(Cipher.ENCRYPT_MODE, privateKey);
+ byte[] encryptedBytes = signCipher.doFinal(query.getBytes());
+ System.out.println(
+ "Bytes encrypted with " + ENCRYPTION_ALGORITHM +
+ ": " + byteArrayToString(
+ encryptedBytes, 0, encryptedBytes.length));
+ return encryptedBytes;
+ }
+
+ private String decryptQuery(byte[] encryptedQuery) throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
+ Cipher verifyCipher = Cipher.getInstance(ENCRYPTION_ALGORITHM);
+ verifyCipher.init(Cipher.DECRYPT_MODE, publicKey);
+ byte[] decryptedBytes = verifyCipher.doFinal(encryptedQuery);
+ System.out.println(
+ "Bytes decrypted with " + ENCRYPTION_ALGORITHM +
+ ": " + byteArrayToString(
+ decryptedBytes, 0, decryptedBytes.length));
+ return new String(decryptedBytes);
+ }
+
+ @Override
+ public byte[] signQuery(String queryName, String queryCode) throws RemoteException {
+ try {
+ return encryptQuery(queryName + queryCode);
+ } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
+ e.printStackTrace();
+ throw new RemoteException(e.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public String checkQuery(byte[] encryptedQuery, String queryName, String queryCode) throws RemoteException {
+ try {
+ return decryptQuery(encryptedQuery);
+ } catch (NoSuchPaddingException | NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
+ e.printStackTrace();
+ throw new RemoteException(e.getLocalizedMessage());
+ }
+ }
+
+ @Override
+ public PublicKey getPublicKey() throws RemoteException {
+ return publicKey;
+ }
+
+ @Override
+ public void setPublicKey(PublicKey publicKey) throws RemoteException {
+ this.publicKey = publicKey;
+ }
+
+ @Override
+ public byte[] getQuerySignature(String queryName) throws RemoteException {
+ return queries.get(queryName).getSignature();
+ }
+}
diff --git a/src/main/java/pl/edu/mimuw/cloudatlas/querysignerapi/QuerySignerApi.java b/src/main/java/pl/edu/mimuw/cloudatlas/querysignerapi/QuerySignerApi.java
new file mode 100644
index 0000000..3c77c0a
--- /dev/null
+++ b/src/main/java/pl/edu/mimuw/cloudatlas/querysignerapi/QuerySignerApi.java
@@ -0,0 +1,17 @@
+package pl.edu.mimuw.cloudatlas.querysignerapi;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.security.PublicKey;
+
+public interface QuerySignerApi extends Remote {
+ public byte[] signQuery(String queryName, String queryCode) throws RemoteException;
+
+ public String checkQuery(byte[] encryptedQuery, String queryName, String queryCode) throws RemoteException;
+
+ public PublicKey getPublicKey() throws RemoteException;
+
+ public void setPublicKey(PublicKey publicKey) throws RemoteException;
+
+ public byte[] getQuerySignature(String queryName) throws RemoteException;
+}