Skip to content

Commit

Permalink
Support evaluation (macro, functions) during json expansion
Browse files Browse the repository at this point in the history
  • Loading branch information
adrienlauer committed Jul 1, 2021
1 parent 637d96d commit c14d744
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.seedstack.coffig.Coffig;
import org.seedstack.coffig.TreeNode;
import org.seedstack.coffig.node.MapNode;
import org.seedstack.coffig.node.NamedNode;
Expand All @@ -23,6 +24,12 @@

public class JsonConfigProcessor implements ConfigurationProcessor {
private final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
private Coffig coffig;

@Override
public void initialize(Coffig coffig) {
this.coffig = coffig;
}

@Override
public void process(MapNode configuration) {
Expand All @@ -39,11 +46,11 @@ public void process(MapNode configuration) {

// Replace the value with the parsed JSON/YAML
toParse.forEach((parent, list) -> list.forEach(key -> {
TreeNode toChange = parent.remove(key);
String newKey = key.substring(0, key.length() - 5);
String rawValue = (String) coffig.getMapper().map(parent.remove(key), String.class);

try {
parent.set(newKey, JacksonProvider.buildTreeFromString(yamlMapper, toChange.value()));
parent.set(newKey, JacksonProvider.buildTreeFromString(yamlMapper, rawValue));
} catch (Exception e) {
parent.set(newKey, new ValueNode(TreeNode.formatNodeError(e)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
package org.seedstack.seed.core.internal.crypto;

import com.google.common.io.BaseEncoding;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.util.concurrent.atomic.AtomicBoolean;
import org.seedstack.coffig.Coffig;
import org.seedstack.coffig.spi.ConfigFunction;
import org.seedstack.coffig.spi.ConfigFunctionHolder;
Expand All @@ -19,25 +16,21 @@
import org.seedstack.seed.crypto.CryptoConfig;
import org.seedstack.seed.crypto.EncryptionService;

import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

public class DecryptFunction implements ConfigFunctionHolder {
private final AtomicBoolean initInProgress = new AtomicBoolean(false);
private EncryptionServiceFactory encryptionServiceFactory;
private CryptoConfig.KeyStoreConfig masterKeyStoreConfig;
private Exception storedException;
private volatile EncryptionService encryptionService;
private Coffig coffig;

@Override
public void initialize(Coffig coffig) {
this.coffig = coffig;
try {
initInProgress.set(true);
coffig.getOptional(CryptoConfig.KeyStoreConfig.class, "crypto.keystores.master").ifPresent(cfg -> {
try {
KeyStore keyStore = new KeyStoreLoader().load(CryptoConfig.MASTER_KEY_STORE_NAME, cfg);
encryptionServiceFactory = new EncryptionServiceFactory(keyStore);
masterKeyStoreConfig = cfg;
} catch (Exception e) {
storedException = e;
}
});
} finally {
initInProgress.set(false);
}
Expand All @@ -50,21 +43,21 @@ public ConfigurationComponent fork() {

@ConfigFunction
String decrypt(String alias, String value) {
if (initInProgress.get()) {
// Cannot decrypt anything during initialization phase
return value;
} else {
if (encryptionServiceFactory == null) {
if (storedException != null) {
throw SeedException.wrap(storedException, CryptoErrorCode.MISSING_MASTER_KEYSTORE);
} else {
throw SeedException.createNew(CryptoErrorCode.MISSING_MASTER_KEYSTORE);
if (encryptionService == null) {
synchronized (this) {
if (encryptionService == null) {
Optional<CryptoConfig.KeyStoreConfig> optional = coffig.getOptional(CryptoConfig.KeyStoreConfig.class, "crypto.keystores.master");
if (optional.isPresent()) {
CryptoConfig.KeyStoreConfig cfg = optional.get();
KeyStore keyStore = new KeyStoreLoader().load(CryptoConfig.MASTER_KEY_STORE_NAME, cfg);
EncryptionServiceFactory encryptionServiceFactory = new EncryptionServiceFactory(keyStore);
encryptionService = CryptoPlugin.getMasterEncryptionService(encryptionServiceFactory, cfg, alias);
} else {
throw SeedException.createNew(CryptoErrorCode.MISSING_MASTER_KEYSTORE);
}
}
}
EncryptionService encryptionService = CryptoPlugin.getMasterEncryptionService(encryptionServiceFactory,
masterKeyStoreConfig,
alias);
return new String(encryptionService.decrypt(BaseEncoding.base16().decode(value)), StandardCharsets.UTF_8);
}
return new String(encryptionService.decrypt(BaseEncoding.base16().decode(value)), StandardCharsets.UTF_8);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@
import org.seedstack.seed.core.fixtures.DummyService1;
import org.seedstack.seed.core.fixtures.Service;
import org.seedstack.seed.core.fixtures.SomeEnum;
import org.seedstack.seed.testing.SystemProperty;
import org.seedstack.seed.testing.junit4.SeedITRunner;
import some.other.pkg.ForeignClass;

@RunWith(SeedITRunner.class)
@SystemProperty(name = "testJsonProp", value = "{ \"key2\": \"val2\" }")
public class ConfigurationIT {
@Inject
private Injector injector;
Expand Down Expand Up @@ -182,6 +184,7 @@ public void configuration_functions() {
public void json_expansion() {
Coffig configuration = injector.getInstance(Application.class).getConfiguration();
assertThat(configuration.get(String.class, "jsonVal.key1")).isEqualTo("val1");
assertThat(configuration.get(String.class, "jsonValThroughSysProp.key2")).isEqualTo("val2");
}

@Test
Expand Down
2 changes: 1 addition & 1 deletion core/src/test/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ functions:
availableUdpPort: $availableUdpPort('port2')
randomUuid: $randomUuid()
jsonVal|json: '{ "key1": "val1" }'

jsonValThroughSysProp|json: ${sys.testJsonProp}
arrayOfMapContainer:
basicProperty: customId
arrayOfMaps:
Expand Down

0 comments on commit c14d744

Please sign in to comment.