package org.araqne.logstorage.engine;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Validate;
import org.araqne.confdb.Config;
import org.araqne.confdb.ConfigDatabase;
import org.araqne.confdb.ConfigIterator;
import org.araqne.confdb.ConfigService;
import org.araqne.confdb.Predicates;
import org.araqne.logstorage.LogCryptoProfile;
import org.araqne.logstorage.LogCryptoProfileRegistry;
import org.araqne.storage.crypto.LogCryptoException;
import org.araqne.storage.crypto.LogCryptoService;
@Component(name = "logstorage-crypto-profile-registry")
@Provides
public class LogCryptoProfileRegistryImpl implements LogCryptoProfileRegistry {
@Requires
private ConfigService conf;
@Requires
private LogCryptoService cryptoService;
private ConcurrentHashMap<String, LogCryptoProfile> profiles = new ConcurrentHashMap<String, LogCryptoProfile>();
@Validate
public void start() {
ConfigDatabase db = conf.ensureDatabase("araqne-logstorage");
ConfigIterator it = db.findAll(LogCryptoProfile.class);
for (LogCryptoProfile p : it.getDocuments(LogCryptoProfile.class)) {
profiles.put(p.getName(), p);
}
}
@Invalidate
public void stop() {
profiles.clear();
}
@Override
public List<LogCryptoProfile> getProfiles() {
return new ArrayList<LogCryptoProfile>(profiles.values());
}
@Override
public LogCryptoProfile getProfile(String name) {
return profiles.get(name);
}
@Override
public void addProfile(LogCryptoProfile profile) {
// verify if profile arguments are valid
if (!new File(profile.getFilePath()).exists())
throw new IllegalArgumentException("key file is not found");
try {
if (profile.getCipher() != null)
cryptoService.newBlockCipher(profile.getCipher(), getRandomBytes(32));
} catch (LogCryptoException e) {
throw new IllegalArgumentException("invalid cipher algorithm", e);
}
try {
if (profile.getCipher() != null && profile.getDigest() == null)
throw new IllegalArgumentException("digest algorithm couldn't be omitted");
if (profile.getDigest() != null)
cryptoService.newMacBuilder(profile.getDigest(), getRandomBytes(32));
} catch (LogCryptoException e) {
throw new IllegalArgumentException("invalid digest algorithm", e);
}
try {
cryptoService.newPkiCipher(profile.getPublicKey(), profile.getPrivateKey());
} catch (LogCryptoException e) {
throw new IllegalArgumentException("invalid public or private key", e);
}
LogCryptoProfile old = profiles.putIfAbsent(profile.getName(), profile);
if (old != null)
throw new IllegalStateException("duplicated crypto profile: " + profile.getName());
ConfigDatabase db = conf.ensureDatabase("araqne-logstorage");
db.add(profile);
}
private byte[] getRandomBytes(int i) {
byte[] result = new byte[i];
new Random().nextBytes(result);
return result;
}
@Override
public void removeProfile(String name) {
ConfigDatabase db = conf.ensureDatabase("araqne-logstorage");
Config c = db.findOne(LogCryptoProfile.class, Predicates.field("name", name));
if (c != null)
c.remove();
LogCryptoProfile old = profiles.remove(name);
if (old == null)
throw new IllegalStateException("crypto profile not found: " + name);
}
}