Skip to content

Commit

Permalink
EPA-164: Better Test Coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasrichner-oviva committed Nov 6, 2024
1 parent 1ef65be commit 06808e3
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,7 @@ public static KeyStores fromKeys(

var federationJwks = federationSigningKey.getKeys().stream().map(JWK::toECKey).toList();

var cache = new ConcurrentHashMap<URI, ECKey>();

Function<URI, ECKey> rpSigningKeyProvider =
uri ->
cache.compute(
uri,
(u, key) -> {
if (key == null) {
key = KeyGenerator.addCertificate(openIdRelyingPartySigningKey, u);
}
return key;
});
var rpSigningKeyProvider = cachedSigningKeyProvider(openIdRelyingPartySigningKey);

return new StaticKeyStores(
rpSigningKeyProvider,
Expand All @@ -133,6 +122,21 @@ public static KeyStores fromKeys(
federationJwks);
}

private static Function<URI, ECKey> cachedSigningKeyProvider(ECKey openIdRelyingPartySigningKey) {

var cache = new ConcurrentHashMap<URI, ECKey>();

return uri ->
cache.compute(
uri,
(u, key) -> {
if (key == null) {
key = KeyGenerator.addCertificate(openIdRelyingPartySigningKey, u);
}
return key;
});
}

static class StaticKeyStores implements KeyStores {

private final Function<URI, ECKey> rpSigKeysProvider;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package com.oviva.ehealthid.relyingparty.providers;

import static org.junit.jupiter.api.Assertions.*;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
import com.oviva.ehealthid.relyingparty.cfg.ConfigProvider;
import com.oviva.ehealthid.relyingparty.test.PropertiesUtils;
import com.oviva.ehealthid.relyingparty.util.KeyGenerator;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

class BasicKeystoreProviderTest {

@Test
void getters() {

var fedKey = KeyGenerator.generateSigningKey();

var sub = URI.create("https://myidp.example.com");
var rpSigKey = KeyGenerator.generateSigningKey();
var provider = Map.of(sub, rpSigKey);

var rpEncKey = KeyGenerator.generateSigningKey();

var opSigKey = KeyGenerator.generateSigningKey();

var sut =
new BasicKeystoreProvider.StaticKeyStores(
provider::get, rpEncKey, opSigKey, List.of(fedKey));

assertEquals(fedKey, sut.federationSigJwksKeystore().keys().get(0));
assertEquals(rpSigKey, sut.relyingPartySigJwksKeystore(sub).keys().get(0));
assertEquals(rpEncKey, sut.relyingPartyEncJwksKeystore().keys().get(0));
assertEquals(opSigKey, sut.openIdProviderJwksKeystore().keys().get(0));
}

@Test
void fromKeys() {

var fedKey = KeyGenerator.generateSigningKey();

var sub = URI.create("https://myidp.example.com");
var rpSigKey = KeyGenerator.generateSigningKey();
rpSigKey = KeyGenerator.addCertificate(rpSigKey, sub);

var rpEncKey = KeyGenerator.generateSigningKey();

var opSigKey = KeyGenerator.generateSigningKey();

var sut = BasicKeystoreProvider.fromKeys(new JWKSet(fedKey), rpSigKey, rpEncKey, opSigKey);

assertEquals(
rpSigKey.getKeyID(), sut.relyingPartySigJwksKeystore(sub).keys().get(0).getKeyID());

assertEquals(fedKey, sut.federationSigJwksKeystore().keys().get(0));
assertEquals(rpEncKey, sut.relyingPartyEncJwksKeystore().keys().get(0));
assertEquals(opSigKey, sut.openIdProviderJwksKeystore().keys().get(0));
}

@Test
void cachedSigKeys() {

var fedKey = KeyGenerator.generateSigningKey();

var sub = URI.create("https://myidp.example.com");
var rpSigKey = KeyGenerator.generateSigningKey();
rpSigKey = KeyGenerator.addCertificate(rpSigKey, sub);

var rpEncKey = KeyGenerator.generateSigningKey();

var opSigKey = KeyGenerator.generateSigningKey();

var sut = BasicKeystoreProvider.fromKeys(new JWKSet(fedKey), rpSigKey, rpEncKey, opSigKey);

var firstInvocation = sut.relyingPartySigJwksKeystore(sub).keys();
var secondInvocation = sut.relyingPartySigJwksKeystore(sub).keys();
var thirdInvocation = sut.relyingPartySigJwksKeystore(sub).keys();

assertEquals(firstInvocation, secondInvocation);
assertEquals(firstInvocation, thirdInvocation);
}

@Test
void loadFromConfig(@TempDir Path tempDir) throws IOException {

var k = new JWKSet(KeyGenerator.generateSigningKey());
var fedKeyName = "fedSigningKey";
var f = Files.writeString(tempDir.resolve(fedKeyName), k.toString(false));

var config =
PropertiesUtils.loadFromString(
"""
federation_es_jwks_path=%s
openid_rp_sig_jwks_path=%s
openid_rp_enc_jwks_path=%s
openid_provider_sig_jwks_path=%s
"""
.formatted(f, f, f, f));

ConfigProvider configProvider = c -> Optional.ofNullable(config.get(c));

// when
var sut = BasicKeystoreProvider.load(configProvider);

// then
var federationSigKeys = sut.federationSigJwksKeystore();
assertEquals(k.getKeys().get(0), federationSigKeys.keys().get(0));
}

@Test
void loadFromConfig_badKeys(@TempDir Path tempDir) throws IOException, JOSEException {

var key =
new RSAKeyGenerator(2048).keyIDFromThumbprint(true).keyUse(KeyUse.SIGNATURE).generate();

var k = new JWKSet(key);
var fedKeyName = "fedSigningKey";
var f = Files.writeString(tempDir.resolve(fedKeyName), k.toString(false));

var config =
PropertiesUtils.loadFromString(
"""
federation_es_jwks_path=%s
openid_rp_sig_jwks_path=%s
openid_rp_enc_jwks_path=%s
openid_provider_sig_jwks_path=%s
"""
.formatted(f, f, f, f));

ConfigProvider configProvider = c -> Optional.ofNullable(config.get(c));

// when & then
assertThrows(IllegalStateException.class, () -> BasicKeystoreProvider.load(configProvider));
}

@Test
void loadFromConfig_noPrivateKey(@TempDir Path tempDir) throws IOException {

var k = new JWKSet(KeyGenerator.generateSigningKey());
var fedKeyName = "fedSigningKey";
var f = Files.writeString(tempDir.resolve(fedKeyName), k.toString(true));

var config =
PropertiesUtils.loadFromString(
"""
federation_es_jwks_path=%s
openid_rp_sig_jwks_path=%s
openid_rp_enc_jwks_path=%s
openid_provider_sig_jwks_path=%s
"""
.formatted(f, f, f, f));

ConfigProvider configProvider = c -> Optional.ofNullable(config.get(c));

// when & then
assertThrows(IllegalStateException.class, () -> BasicKeystoreProvider.load(configProvider));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.oviva.ehealthid.relyingparty.test;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class PropertiesUtils {

public static Map<String, String> loadFromString(String raw) {
try {
var properties = new Properties();
properties.load(new StringReader(raw));
var map = new HashMap<String, String>();
for (String name : properties.stringPropertyNames()) {
map.put(name, properties.getProperty(name));
}
return map;
} catch (IOException e) {
throw new IllegalStateException("failed to parse", e);
}
}
}

0 comments on commit 06808e3

Please sign in to comment.