Implementing JWT bundle and bundle set.
Refactors to X509 bundle and set. Adding tests. Adding library for processing JOSE JWK bundles. Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>
This commit is contained in:
parent
a203cf450f
commit
8c5384ee3b
|
|
@ -54,8 +54,12 @@ dependencies {
|
|||
implementation group: 'io.netty', name: 'netty-transport-native-kqueue', version: "${nettyVersion}", classifier: 'osx-x86_64'
|
||||
compileOnly group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
|
||||
|
||||
// library for processing JWT tokens
|
||||
implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.1'
|
||||
implementation group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.1'
|
||||
implementation group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.1'
|
||||
|
||||
// library for processing JOSE JWK bundles
|
||||
implementation group: 'com.nimbusds', name: 'nimbus-jose-jwt', version: '5.7'
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,24 @@
|
|||
package spiffe.bundle.jwtbundle;
|
||||
|
||||
import com.nimbusds.jose.JOSEException;
|
||||
import com.nimbusds.jose.jwk.ECKey;
|
||||
import com.nimbusds.jose.jwk.JWK;
|
||||
import com.nimbusds.jose.jwk.JWKSet;
|
||||
import com.nimbusds.jose.jwk.RSAKey;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import spiffe.exception.AuthorityNotFoundException;
|
||||
import spiffe.exception.BundleNotFoundException;
|
||||
import spiffe.exception.JwtBundleException;
|
||||
import spiffe.spiffeid.TrustDomain;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyException;
|
||||
import java.security.PublicKey;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
|
@ -23,38 +32,45 @@ public class JwtBundle implements JwtBundleSource {
|
|||
|
||||
Map<String, PublicKey> jwtAuthorities;
|
||||
|
||||
public JwtBundle(@NonNull TrustDomain trustDomain, @NonNull Map<String, PublicKey> jwtAuthorities) {
|
||||
this.trustDomain = trustDomain;
|
||||
this.jwtAuthorities = new ConcurrentHashMap<>(jwtAuthorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new JWT bundle for a trust domain.
|
||||
*
|
||||
* @param trustDomain a {@link TrustDomain} to associate to the JwtBundle
|
||||
*/
|
||||
public JwtBundle(@NonNull TrustDomain trustDomain) {
|
||||
this.trustDomain = trustDomain;
|
||||
this.jwtAuthorities = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bundle from JWT public keys.
|
||||
* Creates a new JWT bundle for a trust domain with JWT Authorities (public keys associated to keyIds).
|
||||
*
|
||||
* @param trustDomain a {@link TrustDomain} to associate to the JwtBundle
|
||||
* @param jwtAuthorities a Map of public Keys
|
||||
* @return a new {@link JwtBundle}.
|
||||
* @param trustDomain a {@link TrustDomain} to associate to the JwtBundle
|
||||
* @param jwtAuthorities a Map of public Keys
|
||||
*/
|
||||
public static JwtBundle fromJWTAuthorities(@NonNull TrustDomain trustDomain, Map<String, PublicKey> jwtAuthorities) {
|
||||
throw new NotImplementedException("Not implemented");
|
||||
public JwtBundle(@NonNull TrustDomain trustDomain, @NonNull Map<String, PublicKey> jwtAuthorities) {
|
||||
this.trustDomain = trustDomain;
|
||||
this.jwtAuthorities = new ConcurrentHashMap<>(jwtAuthorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a bundle from a file on disk.
|
||||
* Loads a bundle from a file on disk. The file must contain a standard RFC 7517 JWKS document.
|
||||
* <p>
|
||||
* Key Types supported are EC and RSA.
|
||||
*
|
||||
* @param trustDomain a {@link TrustDomain} to associate to the JWT bundle.
|
||||
* @param bundlePath a path to a file containing the JWT bundle.
|
||||
* @param bundlePath a path to a file containing the JWT authorities (public keys).
|
||||
* @return a instance of a {@link JwtBundle}
|
||||
* @throws JwtBundleException if there is an error reading or parsing the file, or if a keyId is empty
|
||||
* @throws KeyException if the bundle file contains a key type that is not supported
|
||||
*/
|
||||
public static JwtBundle load(
|
||||
@NonNull final TrustDomain trustDomain,
|
||||
@NonNull final Path bundlePath) {
|
||||
throw new NotImplementedException("Not implemented");
|
||||
public static JwtBundle load(@NonNull final TrustDomain trustDomain, @NonNull final Path bundlePath) throws KeyException, JwtBundleException {
|
||||
try {
|
||||
JWKSet jwkSet = JWKSet.load(bundlePath.toFile());
|
||||
return toJwtBundle(trustDomain, jwkSet);
|
||||
} catch (IOException | ParseException | JOSEException e) {
|
||||
throw new JwtBundleException(String.format("Could not load bundle from file: %s", bundlePath.toString()), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -66,8 +82,13 @@ public class JwtBundle implements JwtBundleSource {
|
|||
*/
|
||||
public static JwtBundle parse(
|
||||
@NonNull final TrustDomain trustDomain,
|
||||
@NonNull final byte[] bundleBytes) {
|
||||
throw new NotImplementedException("Not implemented");
|
||||
@NonNull final byte[] bundleBytes) throws KeyException, JwtBundleException {
|
||||
try {
|
||||
JWKSet jwkSet = JWKSet.parse(new String(bundleBytes));
|
||||
return toJwtBundle(trustDomain, jwkSet);
|
||||
} catch (ParseException | JOSEException e) {
|
||||
throw new JwtBundleException("Could not parse bundle from bytes", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -75,7 +96,6 @@ public class JwtBundle implements JwtBundleSource {
|
|||
*
|
||||
* @param trustDomain a {@link TrustDomain}
|
||||
* @return a {@link JwtBundle} for the trust domain
|
||||
*
|
||||
* @throws BundleNotFoundException if there is no bundle for the given trust domain
|
||||
*/
|
||||
@Override
|
||||
|
|
@ -86,12 +106,18 @@ public class JwtBundle implements JwtBundleSource {
|
|||
throw new BundleNotFoundException(String.format("No JWT bundle found for trust domain %s", trustDomain));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JWT authorities in the bundle, keyed by key ID.
|
||||
*/
|
||||
public Map<String, PublicKey> getJwtAuthorities() {
|
||||
return new HashMap<>(jwtAuthorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the JWT key with the given key id from the bundle.
|
||||
*
|
||||
* @param keyId the Key ID
|
||||
* @return {@link PublicKey} representing the Authority associated to the KeyID.
|
||||
*
|
||||
* @throws AuthorityNotFoundException if no Authority is found associated to the Key ID
|
||||
*/
|
||||
public PublicKey findJwtAuthority(String keyId) throws AuthorityNotFoundException {
|
||||
|
|
@ -102,11 +128,59 @@ public class JwtBundle implements JwtBundleSource {
|
|||
throw new AuthorityNotFoundException(String.format("No authority found for the trust domain %s and key id %s", this.trustDomain, keyId));
|
||||
}
|
||||
|
||||
public void addJWTAuthority(String keyId, PublicKey jwtAuthority) {
|
||||
/**
|
||||
* Returns true if the bundle has a JWT authority with the given key ID.
|
||||
*/
|
||||
public boolean hasJwtAuthority(String keyId) {
|
||||
return jwtAuthorities.containsKey(keyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a JWT authority to the bundle. If a JWT authority already exists
|
||||
* under the given key ID, it is replaced. A key ID must be specified.
|
||||
*
|
||||
* @param keyId Key ID to associate to the jwtAuthority
|
||||
* @param jwtAuthority a PublicKey
|
||||
*/
|
||||
public void addJwtAuthority(@NonNull String keyId, @NonNull PublicKey jwtAuthority) {
|
||||
if (StringUtils.isBlank(keyId)) {
|
||||
throw new IllegalArgumentException("KeyId cannot be empty");
|
||||
}
|
||||
|
||||
jwtAuthorities.put(keyId, jwtAuthority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the JWT authority identified by the key ID from the bundle.
|
||||
*/
|
||||
public void removeJwtAuthority(String keyId) {
|
||||
jwtAuthorities.remove(keyId);
|
||||
}
|
||||
|
||||
private static JwtBundle toJwtBundle(TrustDomain trustDomain, JWKSet jwkSet) throws JwtBundleException, JOSEException, ParseException, KeyException {
|
||||
Map<String, PublicKey> authorities = new HashMap<>();
|
||||
for (JWK jwk : jwkSet.getKeys()) {
|
||||
String keyId = getKeyId(jwk);
|
||||
PublicKey publicKey = getPublicKey(jwk);
|
||||
authorities.put(keyId, publicKey);
|
||||
}
|
||||
return new JwtBundle(trustDomain, authorities);
|
||||
}
|
||||
|
||||
private static String getKeyId(JWK jwk) throws JwtBundleException {
|
||||
String keyId = jwk.getKeyID();
|
||||
if (StringUtils.isBlank(keyId)) {
|
||||
throw new JwtBundleException("Error adding authority of JWKS: keyID cannot be empty");
|
||||
}
|
||||
return keyId;
|
||||
}
|
||||
|
||||
private static PublicKey getPublicKey(JWK jwk) throws JOSEException, ParseException, KeyException {
|
||||
if ("EC".equals(jwk.getKeyType().getValue())) {
|
||||
return ECKey.parse(jwk.toJSONString()).toPublicKey();
|
||||
}
|
||||
if ("RSA".equals(jwk.getKeyType().getValue())) {
|
||||
return RSAKey.parse(jwk.toJSONString()).toPublicKey();
|
||||
}
|
||||
throw new KeyException(String.format("Key Type not supported: %s", jwk.getKeyType().getValue()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ package spiffe.bundle.jwtbundle;
|
|||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
import lombok.val;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import spiffe.exception.BundleNotFoundException;
|
||||
import spiffe.spiffeid.TrustDomain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
|
|
@ -18,8 +19,8 @@ public class JwtBundleSet implements JwtBundleSource {
|
|||
|
||||
ConcurrentHashMap<TrustDomain, JwtBundle> bundles;
|
||||
|
||||
private JwtBundleSet(ConcurrentHashMap<TrustDomain, JwtBundle> bundles) {
|
||||
this.bundles = bundles;
|
||||
private JwtBundleSet(Map<TrustDomain, JwtBundle> bundles) {
|
||||
this.bundles = new ConcurrentHashMap<>(bundles);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -29,7 +30,11 @@ public class JwtBundleSet implements JwtBundleSource {
|
|||
* @return a {@link JwtBundleSet}
|
||||
*/
|
||||
public static JwtBundleSet of(@NonNull final List<JwtBundle> bundles) {
|
||||
throw new NotImplementedException("Not implemented");
|
||||
Map<TrustDomain, JwtBundle> bundleMap = new HashMap<>();
|
||||
for (JwtBundle bundle : bundles) {
|
||||
bundleMap.put(bundle.getTrustDomain(), bundle);
|
||||
}
|
||||
return new JwtBundleSet(bundleMap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -40,7 +45,7 @@ public class JwtBundleSet implements JwtBundleSource {
|
|||
* @throws BundleNotFoundException if no bundle could be found for the given trust domain
|
||||
*/
|
||||
@Override
|
||||
public JwtBundle getJwtBundleForTrustDomain(final TrustDomain trustDomain) throws BundleNotFoundException {
|
||||
public JwtBundle getJwtBundleForTrustDomain(@NonNull final TrustDomain trustDomain) throws BundleNotFoundException {
|
||||
val bundle = bundles.get(trustDomain);
|
||||
if (bundle == null) {
|
||||
throw new BundleNotFoundException(String.format("No JWT bundle for trust domain %s", trustDomain));
|
||||
|
|
@ -48,13 +53,20 @@ public class JwtBundleSet implements JwtBundleSource {
|
|||
return bundles.get(trustDomain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map of JWT bundles keyed by trust domain.
|
||||
*/
|
||||
public Map<TrustDomain, JwtBundle> getBundles() {
|
||||
return new HashMap<>(bundles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add JWT bundle to this set, if the trust domain already exists
|
||||
* replace the bundle.
|
||||
*
|
||||
* @param jwtBundle an instance of a JwtBundle.
|
||||
*/
|
||||
public void add(JwtBundle jwtBundle){
|
||||
throw new NotImplementedException("Not implemented");
|
||||
public void add(@NonNull JwtBundle jwtBundle){
|
||||
bundles.put(jwtBundle.getTrustDomain(), jwtBundle);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,11 +26,22 @@ public class X509Bundle implements X509BundleSource {
|
|||
TrustDomain trustDomain;
|
||||
Set<X509Certificate> x509Authorities;
|
||||
|
||||
/**
|
||||
* Creates a new X.509 bundle for a trust domain.
|
||||
*
|
||||
* @param trustDomain a {@link TrustDomain} to associate to the JwtBundle
|
||||
*/
|
||||
public X509Bundle(@NonNull final TrustDomain trustDomain) {
|
||||
this.trustDomain = trustDomain;
|
||||
this.x509Authorities = ConcurrentHashMap.newKeySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new JWT bundle for a trust domain with X.509 Authorities.
|
||||
*
|
||||
* @param trustDomain a {@link TrustDomain} to associate to the JwtBundle
|
||||
* @param x509Authorities a Map of X.509 Certificates
|
||||
*/
|
||||
public X509Bundle(@NonNull final TrustDomain trustDomain, @NonNull final Set<X509Certificate> x509Authorities) {
|
||||
this.trustDomain = trustDomain;
|
||||
this.x509Authorities = ConcurrentHashMap.newKeySet();
|
||||
|
|
@ -49,7 +60,7 @@ public class X509Bundle implements X509BundleSource {
|
|||
* @throws CertificateException if the bundle cannot be parsed
|
||||
*/
|
||||
public static X509Bundle load(@NonNull final TrustDomain trustDomain, @NonNull final Path bundlePath) throws IOException, CertificateException {
|
||||
byte[] bundleBytes = new byte[0];
|
||||
byte[] bundleBytes;
|
||||
try {
|
||||
bundleBytes = Files.readAllBytes(bundlePath);
|
||||
} catch (NoSuchFileException e) {
|
||||
|
|
@ -93,6 +104,13 @@ public class X509Bundle implements X509BundleSource {
|
|||
throw new BundleNotFoundException(String.format("No X509 bundle found for trust domain %s", trustDomain));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X.509 x509Authorities in the bundle.
|
||||
*/
|
||||
public Set<X509Certificate> getX509Authorities() {
|
||||
return new HashSet<>(x509Authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given X.509 authority exists in the bundle.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import lombok.val;
|
|||
import spiffe.exception.BundleNotFoundException;
|
||||
import spiffe.spiffeid.TrustDomain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
|
|
@ -17,8 +19,8 @@ public class X509BundleSet implements X509BundleSource {
|
|||
|
||||
ConcurrentHashMap<TrustDomain, X509Bundle> bundles;
|
||||
|
||||
private X509BundleSet(final ConcurrentHashMap<TrustDomain, X509Bundle> bundles) {
|
||||
this.bundles = bundles;
|
||||
private X509BundleSet(final Map<TrustDomain, X509Bundle> bundles) {
|
||||
this.bundles = new ConcurrentHashMap<>(bundles);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -28,7 +30,7 @@ public class X509BundleSet implements X509BundleSource {
|
|||
* @return a {@link X509BundleSet} initialized with the list of bundles
|
||||
*/
|
||||
public static X509BundleSet of(@NonNull final List<X509Bundle> bundles) {
|
||||
ConcurrentHashMap<TrustDomain, X509Bundle> bundleMap = new ConcurrentHashMap<>();
|
||||
Map<TrustDomain, X509Bundle> bundleMap = new HashMap<>();
|
||||
for (X509Bundle bundle : bundles) {
|
||||
bundleMap.put(bundle.getTrustDomain(), bundle);
|
||||
}
|
||||
|
|
@ -60,4 +62,8 @@ public class X509BundleSet implements X509BundleSource {
|
|||
}
|
||||
return bundles.get(trustDomain);
|
||||
}
|
||||
|
||||
public Map<TrustDomain, X509Bundle> getBundles() {
|
||||
return new HashMap<>(bundles);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package spiffe.exception;
|
||||
|
||||
/**
|
||||
* Checked exception thrown when there is an error creating a JwtBundle
|
||||
*/
|
||||
public class JwtBundleException extends Exception {
|
||||
public JwtBundleException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public JwtBundleException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public JwtBundleException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
package spiffe.bundle.jwtbundle;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import spiffe.exception.BundleNotFoundException;
|
||||
import spiffe.internal.DummyPublicKey;
|
||||
import spiffe.spiffeid.TrustDomain;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class JwtBundleSetTest {
|
||||
|
||||
@Test
|
||||
void testOfListOfBundles() {
|
||||
JwtBundle jwtBundle1 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
JwtBundle jwtBundle2 = new JwtBundle(TrustDomain.of("other.org"));
|
||||
|
||||
List<JwtBundle> bundles = Arrays.asList(jwtBundle1, jwtBundle2);
|
||||
|
||||
JwtBundleSet bundleSet = JwtBundleSet.of(bundles);
|
||||
|
||||
assertNotNull(bundleSet);
|
||||
assertEquals(2, bundleSet.getBundles().size());
|
||||
assertEquals(jwtBundle1, bundleSet.getBundles().get(TrustDomain.of("example.org")));
|
||||
assertEquals(jwtBundle2, bundleSet.getBundles().get(TrustDomain.of("other.org")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getJwtBundleForTrustDomain_Success() {
|
||||
JwtBundle jwtBundle1 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
JwtBundle jwtBundle2 = new JwtBundle(TrustDomain.of("other.org"));
|
||||
List<JwtBundle> bundles = Arrays.asList(jwtBundle1, jwtBundle2);
|
||||
JwtBundleSet bundleSet = JwtBundleSet.of(bundles);
|
||||
|
||||
JwtBundle bundle = null;
|
||||
try {
|
||||
bundle = bundleSet.getJwtBundleForTrustDomain(TrustDomain.of("example.org"));
|
||||
} catch (BundleNotFoundException e) {
|
||||
fail(e);
|
||||
}
|
||||
|
||||
assertEquals(jwtBundle1, bundle);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOf_null_throwsNullPointerException() {
|
||||
try {
|
||||
JwtBundleSet.of(null);
|
||||
fail("should have thrown exception");
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("bundles is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetJwtBundleForTrustDomain_TrustDomainNotInSet_ThrowsBundleNotFoundException() {
|
||||
JwtBundle jwtBundle1 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
JwtBundle jwtBundle2 = new JwtBundle(TrustDomain.of("other.org"));
|
||||
List<JwtBundle> bundles = Arrays.asList(jwtBundle1, jwtBundle2);
|
||||
JwtBundleSet bundleSet = JwtBundleSet.of(bundles);
|
||||
|
||||
try {
|
||||
bundleSet.getJwtBundleForTrustDomain(TrustDomain.of("domain.test"));
|
||||
fail("exception expected");
|
||||
} catch (BundleNotFoundException e) {
|
||||
assertEquals("No JWT bundle for trust domain domain.test", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetJwtBundleForTrustDomain_null_throwsNullPointerException() throws BundleNotFoundException {
|
||||
JwtBundle jwtBundle1 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
List<JwtBundle> bundleList = Collections.singletonList(jwtBundle1);
|
||||
JwtBundleSet bundleSet = JwtBundleSet.of(bundleList);
|
||||
try {
|
||||
bundleSet.getJwtBundleForTrustDomain(null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("trustDomain is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAdd() {
|
||||
JwtBundle jwtBundle1 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
List<JwtBundle> bundleList = Collections.singletonList(jwtBundle1);
|
||||
JwtBundleSet bundleSet = JwtBundleSet.of(bundleList);
|
||||
|
||||
JwtBundle jwtBundle2 = new JwtBundle(TrustDomain.of("other.org"));
|
||||
bundleSet.add(jwtBundle2);
|
||||
|
||||
assertTrue(bundleSet.getBundles().containsValue(jwtBundle1));
|
||||
assertTrue(bundleSet.getBundles().containsValue(jwtBundle2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAdd_sameBundleAgain_noDuplicate() {
|
||||
JwtBundle jwtBundle1 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
List<JwtBundle> bundleList = Collections.singletonList(jwtBundle1);
|
||||
JwtBundleSet bundleSet = JwtBundleSet.of(bundleList);
|
||||
|
||||
bundleSet.add(jwtBundle1);
|
||||
|
||||
assertEquals(1, bundleSet.getBundles().size());
|
||||
assertTrue(bundleSet.getBundles().containsValue(jwtBundle1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAdd_aDifferentBundleForSameTrustDomain_replacesWithNewBundle() {
|
||||
JwtBundle jwtBundle1 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
List<JwtBundle> bundleList = Collections.singletonList(jwtBundle1);
|
||||
JwtBundleSet bundleSet = JwtBundleSet.of(bundleList);
|
||||
|
||||
JwtBundle jwtBundle2 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
jwtBundle2.addJwtAuthority("key1", new DummyPublicKey());
|
||||
bundleSet.add(jwtBundle2);
|
||||
|
||||
assertTrue(bundleSet.getBundles().containsValue(jwtBundle2));
|
||||
assertFalse(bundleSet.getBundles().containsValue(jwtBundle1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void add_null_throwsNullPointerException() {
|
||||
JwtBundle jwtBundle1 = new JwtBundle(TrustDomain.of("example.org"));
|
||||
List<JwtBundle> bundleList = Collections.singletonList(jwtBundle1);
|
||||
JwtBundleSet bundleSet = JwtBundleSet.of(bundleList);
|
||||
try {
|
||||
bundleSet.add(null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("jwtBundle is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,350 @@
|
|||
package spiffe.bundle.jwtbundle;
|
||||
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import spiffe.exception.AuthorityNotFoundException;
|
||||
import spiffe.exception.BundleNotFoundException;
|
||||
import spiffe.exception.JwtBundleException;
|
||||
import spiffe.internal.DummyPublicKey;
|
||||
import spiffe.spiffeid.TrustDomain;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class JwtBundleTest {
|
||||
|
||||
@Test
|
||||
void testNewJwtBundleWithTrustDomain_Success() {
|
||||
JwtBundle jwtBundle = new JwtBundle(TrustDomain.of("example.org"));
|
||||
assertNotNull(jwtBundle);
|
||||
assertEquals(TrustDomain.of("example.org"), jwtBundle.getTrustDomain());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNewJwtBundleWithTrustDomainAndAuthorities_Success() {
|
||||
HashMap<String, PublicKey> authorities = new HashMap<>();
|
||||
KeyPair key1 = Keys.keyPairFor(SignatureAlgorithm.ES384);
|
||||
KeyPair key2 = Keys.keyPairFor(SignatureAlgorithm.PS256);
|
||||
|
||||
authorities.put("authority1", key1.getPublic());
|
||||
authorities.put("authority2", key2.getPublic());
|
||||
|
||||
JwtBundle jwtBundle = new JwtBundle(TrustDomain.of("example.org"), authorities);
|
||||
|
||||
// change a key in the map, to test that the bundle has its own copy
|
||||
authorities.put("authority1", key2.getPublic());
|
||||
|
||||
assertNotNull(jwtBundle);
|
||||
assertEquals(TrustDomain.of("example.org"), jwtBundle.getTrustDomain());
|
||||
assertEquals(2, jwtBundle.getJwtAuthorities().size());
|
||||
assertEquals(key1.getPublic(), jwtBundle.getJwtAuthorities().get("authority1"));
|
||||
assertEquals(key2.getPublic(), jwtBundle.getJwtAuthorities().get("authority2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNewJwtBundle_TrustDomainIsNull_ThrowsNullPointerException() {
|
||||
try {
|
||||
HashMap<String, PublicKey> authorities = new HashMap<>();
|
||||
new JwtBundle(null, authorities);
|
||||
fail("NullPointerException was expected");
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("trustDomain is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNewJwtBundleWithTrustDomain_AuthoritiesIsNull_ThrowsNullPointerException() {
|
||||
try {
|
||||
new JwtBundle(TrustDomain.of("example.org"), null);
|
||||
fail("NullPointerException was expected");
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("jwtAuthorities is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNewJwtBundleWithAuthorities_TrustDomainIsNull_ThrowsNullPointerException() {
|
||||
try {
|
||||
new JwtBundle(null);
|
||||
fail("NullPointerException was expected");
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("trustDomain is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadFileWithEcKey_Success() throws URISyntaxException {
|
||||
Path path = Paths.get(toUri("testdata/jwtbundle/jwks_valid_EC_1.json"));
|
||||
TrustDomain trustDomain = TrustDomain.of("example.org");
|
||||
|
||||
JwtBundle jwtBundle = null;
|
||||
try {
|
||||
jwtBundle = JwtBundle.load(trustDomain, path);
|
||||
} catch (KeyException | JwtBundleException e) {
|
||||
fail();
|
||||
}
|
||||
|
||||
assertNotNull(jwtBundle);
|
||||
assertEquals(TrustDomain.of("example.org"), jwtBundle.getTrustDomain());
|
||||
assertEquals(1, jwtBundle.getJwtAuthorities().size());
|
||||
assertNotNull(jwtBundle.getJwtAuthorities().get("C6vs25welZOx6WksNYfbMfiw9l96pMnD"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadFileWithRsaKey_Success() throws URISyntaxException {
|
||||
Path path = Paths.get(toUri("testdata/jwtbundle/jwks_valid_RSA_1.json"));
|
||||
TrustDomain trustDomain = TrustDomain.of("domain.test");
|
||||
|
||||
JwtBundle jwtBundle = null;
|
||||
try {
|
||||
jwtBundle = JwtBundle.load(trustDomain, path);
|
||||
} catch (KeyException | JwtBundleException e) {
|
||||
fail(e);
|
||||
}
|
||||
|
||||
assertNotNull(jwtBundle);
|
||||
assertEquals(TrustDomain.of("domain.test"), jwtBundle.getTrustDomain());
|
||||
assertEquals(1, jwtBundle.getJwtAuthorities().size());
|
||||
assertNotNull(jwtBundle.getJwtAuthorities().get("14cc39cd-838d-426d-9bb1-77f3468fba96"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadFileWithRsaAndEc_Success() throws URISyntaxException {
|
||||
Path path = Paths.get(toUri("testdata/jwtbundle/jwks_valid_RSA_EC.json"));
|
||||
TrustDomain trustDomain = TrustDomain.of("domain.test");
|
||||
|
||||
JwtBundle jwtBundle = null;
|
||||
try {
|
||||
jwtBundle = JwtBundle.load(trustDomain, path);
|
||||
} catch (KeyException | JwtBundleException e) {
|
||||
fail(e);
|
||||
}
|
||||
|
||||
assertNotNull(jwtBundle);
|
||||
assertEquals(TrustDomain.of("domain.test"), jwtBundle.getTrustDomain());
|
||||
assertEquals(2, jwtBundle.getJwtAuthorities().size());
|
||||
assertNotNull(jwtBundle.getJwtAuthorities().get("14cc39cd-838d-426d-9bb1-77f3468fba96"));
|
||||
assertNotNull(jwtBundle.getJwtAuthorities().get("C6vs25welZOx6WksNYfbMfiw9l96pMnD"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadFile_MissingKid_ThrowsJwtBundleException() throws URISyntaxException, KeyException {
|
||||
Path path = Paths.get(toUri("testdata/jwtbundle/jwks_missing_kid.json"));
|
||||
TrustDomain trustDomain = TrustDomain.of("domain.test");
|
||||
|
||||
try {
|
||||
JwtBundle.load(trustDomain, path);
|
||||
fail("should have thrown exception");
|
||||
} catch (JwtBundleException e) {
|
||||
assertEquals("Error adding authority of JWKS: keyID cannot be empty", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadFile_InvalidKeyType_ThrowsKeyException() throws URISyntaxException, JwtBundleException {
|
||||
Path path = Paths.get(toUri("testdata/jwtbundle/jwks_invalid_keytype.json"));
|
||||
TrustDomain trustDomain = TrustDomain.of("domain.test");
|
||||
|
||||
try {
|
||||
JwtBundle.load(trustDomain, path);
|
||||
fail("should have thrown exception");
|
||||
} catch (KeyException e) {
|
||||
assertEquals("Key Type not supported: OKP", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadFile_NonExistentFile_ThrowsException() throws KeyException {
|
||||
Path path = Paths.get("testdata/jwtbundle/non-existen.json");
|
||||
TrustDomain trustDomain = TrustDomain.of("domain.test");
|
||||
|
||||
try {
|
||||
JwtBundle.load(trustDomain, path);
|
||||
fail("should have thrown exception");
|
||||
} catch (JwtBundleException e) {
|
||||
assertEquals("Could not load bundle from file: testdata/jwtbundle/non-existen.json", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoad_NullTrustDomain_ThrowsNullPointerException() throws KeyException, JwtBundleException {
|
||||
try {
|
||||
JwtBundle.load(null, Paths.get("path-to-file"));
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("trustDomain is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoad_NullBundlePath_ThrowsNullPointerException() throws KeyException, JwtBundleException {
|
||||
try {
|
||||
JwtBundle.load(TrustDomain.of("example.org"), null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("bundlePath is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseJsonWithRsaAndEcKeys_Success() throws URISyntaxException, IOException {
|
||||
Path path = Paths.get(toUri("testdata/jwtbundle/jwks_valid_RSA_EC.json"));
|
||||
byte[] bundleBytes = Files.readAllBytes(path);
|
||||
|
||||
JwtBundle jwtBundle = null;
|
||||
try {
|
||||
jwtBundle = JwtBundle.parse(TrustDomain.of("domain.test"), bundleBytes);
|
||||
} catch (KeyException | JwtBundleException e) {
|
||||
fail(e);
|
||||
}
|
||||
|
||||
assertNotNull(jwtBundle);
|
||||
assertEquals(TrustDomain.of("domain.test"), jwtBundle.getTrustDomain());
|
||||
assertEquals(2, jwtBundle.getJwtAuthorities().size());
|
||||
assertNotNull(jwtBundle.getJwtAuthorities().get("14cc39cd-838d-426d-9bb1-77f3468fba96"));
|
||||
assertNotNull(jwtBundle.getJwtAuthorities().get("C6vs25welZOx6WksNYfbMfiw9l96pMnD"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParse_MissingKid_Fails() throws URISyntaxException, IOException {
|
||||
Path path = Paths.get(toUri("testdata/jwtbundle/jwks_missing_kid.json"));
|
||||
byte[] bundleBytes = Files.readAllBytes(path);
|
||||
TrustDomain trustDomain = TrustDomain.of("domain.test");
|
||||
|
||||
try {
|
||||
JwtBundle.parse(trustDomain, bundleBytes);
|
||||
fail("should have thrown exception");
|
||||
} catch (KeyException | JwtBundleException e) {
|
||||
assertEquals("Error adding authority of JWKS: keyID cannot be empty", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseInvalidJson() throws KeyException {
|
||||
try {
|
||||
JwtBundle.parse(TrustDomain.of("example.org"), "invalid json".getBytes());
|
||||
fail("exception is expected");
|
||||
} catch (JwtBundleException e) {
|
||||
assertEquals("Could not parse bundle from bytes", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParse_NullTrustDomain_ThrowsNullPointerException() throws KeyException, JwtBundleException {
|
||||
try {
|
||||
JwtBundle.parse(null, "json".getBytes());
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("trustDomain is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParse_NullBundleBytes_ThrowsNullPointerException() throws KeyException, JwtBundleException {
|
||||
try {
|
||||
JwtBundle.parse(TrustDomain.of("example.org"), null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("bundleBytes is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testGetJwtBundleForTrustDomain_Success() {
|
||||
JwtBundle jwtBundle = new JwtBundle(TrustDomain.of("example.org"));
|
||||
try {
|
||||
JwtBundle bundle = jwtBundle.getJwtBundleForTrustDomain(TrustDomain.of("example.org"));
|
||||
assertEquals(jwtBundle, bundle);
|
||||
} catch (BundleNotFoundException e) {
|
||||
fail(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetJwtBundleForTrustDomain_doesNotExiste_ThrowsBundleNotFoundException() {
|
||||
JwtBundle jwtBundle = new JwtBundle(TrustDomain.of("example.org"));
|
||||
try {
|
||||
jwtBundle.getJwtBundleForTrustDomain(TrustDomain.of("other.org"));
|
||||
fail("exception expected");
|
||||
} catch (BundleNotFoundException e) {
|
||||
assertEquals("No JWT bundle found for trust domain other.org", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testJWTAuthoritiesCRUD() {
|
||||
JwtBundle jwtBundle = new JwtBundle(TrustDomain.of("example.org"));
|
||||
|
||||
// Test addJWTAuthority
|
||||
DummyPublicKey jwtAuthority1 = new DummyPublicKey();
|
||||
DummyPublicKey jwtAuthority2 = new DummyPublicKey();
|
||||
jwtBundle.addJwtAuthority("key1", jwtAuthority1);
|
||||
jwtBundle.addJwtAuthority("key2", jwtAuthority2);
|
||||
|
||||
assertEquals(2, jwtBundle.getJwtAuthorities().size());
|
||||
|
||||
// Test findJwtAuthority
|
||||
PublicKey key1 = null;
|
||||
PublicKey key2 = null;
|
||||
try {
|
||||
key1 = jwtBundle.findJwtAuthority("key1");
|
||||
key2 = jwtBundle.findJwtAuthority("key2");
|
||||
} catch (AuthorityNotFoundException e) {
|
||||
fail(e);
|
||||
}
|
||||
assertEquals(key1, jwtAuthority1 );
|
||||
assertEquals(key2, jwtAuthority2 );
|
||||
|
||||
// Test RemoveJwtAuthority
|
||||
jwtBundle.removeJwtAuthority("key1");
|
||||
assertFalse(jwtBundle.hasJwtAuthority("key1"));
|
||||
assertTrue(jwtBundle.hasJwtAuthority("key2"));
|
||||
|
||||
// Test update
|
||||
jwtBundle.addJwtAuthority("key2", jwtAuthority1);
|
||||
assertEquals(jwtAuthority1, jwtBundle.getJwtAuthorities().get("key2"));
|
||||
assertEquals(1, jwtBundle.getJwtAuthorities().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddJwtAuthority_emtpyKeyId_throwsIllegalArgumentException() {
|
||||
JwtBundle jwtBundle = new JwtBundle(TrustDomain.of("example.org"));
|
||||
try {
|
||||
jwtBundle.addJwtAuthority("", new DummyPublicKey());
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals("KeyId cannot be empty", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddJwtAuthority_nullKeyId_throwsNullPointerException() {
|
||||
JwtBundle jwtBundle = new JwtBundle(TrustDomain.of("example.org"));
|
||||
try {
|
||||
jwtBundle.addJwtAuthority(null, new DummyPublicKey());
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("keyId is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddJwtAuthority_nullJwtAuthority_throwsNullPointerException() {
|
||||
JwtBundle jwtBundle = new JwtBundle(TrustDomain.of("example.org"));
|
||||
try {
|
||||
jwtBundle.addJwtAuthority("key1", null);
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("jwtAuthority is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private URI toUri(String path) throws URISyntaxException {
|
||||
return getClass().getClassLoader().getResource(path).toURI();
|
||||
}
|
||||
}
|
||||
|
|
@ -20,8 +20,8 @@ class X509BundleSetTest {
|
|||
List<X509Bundle> bundleList = Arrays.asList(x509Bundle1, x509Bundle2);
|
||||
X509BundleSet bundleSet = X509BundleSet.of(bundleList);
|
||||
|
||||
assertTrue(bundleSet.getBundles().contains(x509Bundle1));
|
||||
assertTrue(bundleSet.getBundles().contains(x509Bundle2));
|
||||
assertTrue(bundleSet.getBundles().containsValue(x509Bundle1));
|
||||
assertTrue(bundleSet.getBundles().containsValue(x509Bundle2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -43,8 +43,8 @@ class X509BundleSetTest {
|
|||
X509Bundle x509Bundle2 = new X509Bundle(TrustDomain.of("other.org"));
|
||||
bundleSet.add(x509Bundle2);
|
||||
|
||||
assertTrue(bundleSet.getBundles().contains(x509Bundle1));
|
||||
assertTrue(bundleSet.getBundles().contains(x509Bundle2));
|
||||
assertTrue(bundleSet.getBundles().containsValue(x509Bundle1));
|
||||
assertTrue(bundleSet.getBundles().containsValue(x509Bundle2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -55,7 +55,7 @@ class X509BundleSetTest {
|
|||
|
||||
bundleSet.add(x509Bundle1);
|
||||
|
||||
assertTrue(bundleSet.getBundles().contains(x509Bundle1));
|
||||
assertTrue(bundleSet.getBundles().containsValue(x509Bundle1));
|
||||
assertEquals(1, bundleSet.getBundles().size());
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +69,8 @@ class X509BundleSetTest {
|
|||
x509Bundle2.addX509Authority(new DummyX509Certificate());
|
||||
bundleSet.add(x509Bundle2);
|
||||
|
||||
assertTrue(bundleSet.getBundles().contains(x509Bundle2));
|
||||
assertFalse(bundleSet.getBundles().contains(x509Bundle1));
|
||||
assertTrue(bundleSet.getBundles().containsValue(x509Bundle2));
|
||||
assertFalse(bundleSet.getBundles().containsValue(x509Bundle1));
|
||||
assertEquals(1, bundleSet.getBundles().size());
|
||||
}
|
||||
|
||||
|
|
@ -128,8 +128,4 @@ class X509BundleSetTest {
|
|||
assertEquals("trustDomain is marked non-null but is null", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBundles() {
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package spiffe.internal;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class DummyPublicKey implements PublicKey {
|
||||
@Override
|
||||
public String getAlgorithm() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormat() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return new byte[0];
|
||||
}
|
||||
}
|
||||
|
|
@ -108,8 +108,8 @@ class JwtSvidParseAndValidateTest {
|
|||
|
||||
TrustDomain trustDomain = TrustDomain.of("test.domain");
|
||||
JwtBundle jwtBundle = new JwtBundle(trustDomain);
|
||||
jwtBundle.addJWTAuthority("authority1", key1.getPublic());
|
||||
jwtBundle.addJWTAuthority("authority2", key2.getPublic());
|
||||
jwtBundle.addJwtAuthority("authority1", key1.getPublic());
|
||||
jwtBundle.addJwtAuthority("authority2", key2.getPublic());
|
||||
|
||||
SpiffeId spiffeId = trustDomain.newSpiffeId("host");
|
||||
Date expiration = new Date(System.currentTimeMillis() + 3600000);
|
||||
|
|
|
|||
|
|
@ -94,8 +94,8 @@ class JwtSvidParseInsecureTest {
|
|||
|
||||
TrustDomain trustDomain = TrustDomain.of("test.domain");
|
||||
JwtBundle jwtBundle = new JwtBundle(trustDomain);
|
||||
jwtBundle.addJWTAuthority("authority1", key1.getPublic());
|
||||
jwtBundle.addJWTAuthority("authority2", key2.getPublic());
|
||||
jwtBundle.addJwtAuthority("authority1", key1.getPublic());
|
||||
jwtBundle.addJwtAuthority("authority2", key2.getPublic());
|
||||
|
||||
SpiffeId spiffeId = trustDomain.newSpiffeId("host");
|
||||
Date expiration = new Date(System.currentTimeMillis() + 3600000);
|
||||
|
|
|
|||
11
java-spiffe-core/src/test/resources/testdata/jwtbundle/jwks_invalid_keytype.json
vendored
Normal file
11
java-spiffe-core/src/test/resources/testdata/jwtbundle/jwks_invalid_keytype.json
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"keys": [
|
||||
{
|
||||
"kty": "OKP",
|
||||
"crv": "Ed25519",
|
||||
"kid": "1",
|
||||
"x": "c2Rmc2Zk",
|
||||
"alg": "EdDSA"
|
||||
}
|
||||
]
|
||||
}
|
||||
17
java-spiffe-core/src/test/resources/testdata/jwtbundle/jwks_missing_kid.json
vendored
Normal file
17
java-spiffe-core/src/test/resources/testdata/jwtbundle/jwks_missing_kid.json
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"keys": [
|
||||
{
|
||||
"kty": "EC",
|
||||
"kid": "C6vs25welZOx6WksNYfbMfiw9l96pMnD",
|
||||
"crv": "P-256",
|
||||
"x": "ngLYQnlfF6GsojUwqtcEE3WgTNG2RUlsGhK73RNEl5k",
|
||||
"y": "tKbiDSUSsQ3F1P7wteeHNXIcU-cx6CgSbroeQrQHTLM"
|
||||
},
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": "P-256",
|
||||
"x": "7MGOl06DP9df2u8oHY6lqYFIoQWzCj9UYlp-MFeEYeY",
|
||||
"y": "PSLLy5Pg0_kNGFFXq_eeq9kYcGDM3MPHJ6ncteNOr6w"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"keys": [
|
||||
{
|
||||
"kty": "EC",
|
||||
"kid": "C6vs25welZOx6WksNYfbMfiw9l96pMnD",
|
||||
"crv": "P-256",
|
||||
"x": "ngLYQnlfF6GsojUwqtcEE3WgTNG2RUlsGhK73RNEl5k",
|
||||
"y": "tKbiDSUSsQ3F1P7wteeHNXIcU-cx6CgSbroeQrQHTLM"
|
||||
}
|
||||
]
|
||||
}
|
||||
17
java-spiffe-core/src/test/resources/testdata/jwtbundle/jwks_valid_RSA_1.json
vendored
Normal file
17
java-spiffe-core/src/test/resources/testdata/jwtbundle/jwks_valid_RSA_1.json
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"keys": [
|
||||
{
|
||||
"p": "4aCuWvrpN7CeAqmXUWoQHex9l0ePELKe9AzJ2jcnDPEqP_CO9jlL7V_ZlMFLXg8oSFMkx59woD3BCjdZqCDaaiWA8L3fFmcLXLj9LrTz0X_p_Tb1cPbCa3Z5MqtuhC5yg5Po8uuDOUrF4FdKcU_YtCYbFwsr4HfViakKlk64Qt8",
|
||||
"kty": "RSA",
|
||||
"q": "o7Enkd4yxw9tl-jHQXw38GjItzdbFLmkeppHSIzv02Zs5XS0CQyb-jFrUXStpO3UiNrRXm1YUCSUwRDj81ATilrIpPTTH6qC2Fu_E5eEEDx79W5p0oj3SbN2BQS5-MkhVvMrrDGkIAmRmLcE9SH-eIreYgB6XW0yrbHTwbUWV98",
|
||||
"d": "EpfAjuifddpKISal0znpNhlfVkRDyEdd6_CBlh6lLJdU8dflcqyWFhmJ8pEXsnwC4-DBkkDKt57HcIq3MQ8Q_IKlhLPexugNr3QJxbA1DCbXagsIvh4-QcBQp-4LOZv1T3T4-lywkRzX0qp9yjySIGkT6OmAfN97Q-_NPhOdlHJn5feQfJhxWIMaWhQnomjmMP40FApRdk-gOmNx-w2pLWHVjnibbfI9SijUKg4ZqW3MvwNbSuM-EPyetRuaJRW892h7kxGE2wV_oqGRbqasPqVJN9SiNAEWwzcs645NwPEC48XUK0Q4eUyd9ra_YFv9HGgZ1Yo0gaD0BnRMLxcm-Q",
|
||||
"e": "AQAB",
|
||||
"use": "sig",
|
||||
"kid": "14cc39cd-838d-426d-9bb1-77f3468fba96",
|
||||
"qi": "kly84cu6D3sy64HfRpXfIYuNZTcJxlfdkLcLY-ZHkY5oVUiDBb6VrKwkQq3e5UbxF0a6qzwCk_B0Bn6ChHXLorVLnlx8cUG2TP3C72J_iHpE8Bn3wend7ZqLfcceh19zPOe13352RurPXbewzf1tYVji-OPzJr05fUDrqmesXvI",
|
||||
"dp": "XTZnsbiFDvfNX6Y2mHDr9aDVBeGPTkOs_YAnCBrO7D7ZyI6WUUy8fHWjyxvMCjDS4IZQ5JOPEPRSQuk5BgeElGOoEE0w0-2AOS9Hkbs6G2vv_CdvYNrg2UqZqYA_aSZTMt6xV2JK1Sl59EO7wnJNQaeYe32nA9YeBwAqGoys_Rs",
|
||||
"dq": "GeTJLKLoh2KiZHhXJL3An5ADyC_CganIIfjLs-dPfLJkIXvvisrq1Y4BuvXpDgDtMOTkX7qOUMconM3OMUwGe0lXGfj8eLLhVdZViITcSDE5Lp7TsJEoBQmVbr_Lp1Yxpu56hxenLcY1uOGisCA7f9f_y6LluGewr5dEtwytRyM",
|
||||
"n": "kEVx_IUSr30PMuJTWWg4QYxhOWU80Zl_OKHnGp6PxLqD0wuOmLQv2a0xprzXMIxROl3iYyAY_PQmiLQn4aMR_c55V6N6O_qP5d09tArAipMsVyAICW0RRtJtAL-n9_ktghmYUaVHhq5AXS7flxO2b8KKZWZuKJ1f8clbK16eOJ_-NURjqz90zpuafIA1nzCdNk9AE1NOuXdW81FIjC-82abgDhgyNgNnL33z8BXbwKdog0Hu9BFoyIBXIA8HLzaj-KmyqTY9ewu2JVI8XVLuM_zy-6FmzKGanw0bhZRAFNHc-eraMP0HLJuWf0R9waiKmrPy0i6zISayo4_rm2YJQQ"
|
||||
}
|
||||
]
|
||||
}
|
||||
24
java-spiffe-core/src/test/resources/testdata/jwtbundle/jwks_valid_RSA_EC.json
vendored
Normal file
24
java-spiffe-core/src/test/resources/testdata/jwtbundle/jwks_valid_RSA_EC.json
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"keys": [
|
||||
{
|
||||
"p": "4aCuWvrpN7CeAqmXUWoQHex9l0ePELKe9AzJ2jcnDPEqP_CO9jlL7V_ZlMFLXg8oSFMkx59woD3BCjdZqCDaaiWA8L3fFmcLXLj9LrTz0X_p_Tb1cPbCa3Z5MqtuhC5yg5Po8uuDOUrF4FdKcU_YtCYbFwsr4HfViakKlk64Qt8",
|
||||
"kty": "RSA",
|
||||
"q": "o7Enkd4yxw9tl-jHQXw38GjItzdbFLmkeppHSIzv02Zs5XS0CQyb-jFrUXStpO3UiNrRXm1YUCSUwRDj81ATilrIpPTTH6qC2Fu_E5eEEDx79W5p0oj3SbN2BQS5-MkhVvMrrDGkIAmRmLcE9SH-eIreYgB6XW0yrbHTwbUWV98",
|
||||
"d": "EpfAjuifddpKISal0znpNhlfVkRDyEdd6_CBlh6lLJdU8dflcqyWFhmJ8pEXsnwC4-DBkkDKt57HcIq3MQ8Q_IKlhLPexugNr3QJxbA1DCbXagsIvh4-QcBQp-4LOZv1T3T4-lywkRzX0qp9yjySIGkT6OmAfN97Q-_NPhOdlHJn5feQfJhxWIMaWhQnomjmMP40FApRdk-gOmNx-w2pLWHVjnibbfI9SijUKg4ZqW3MvwNbSuM-EPyetRuaJRW892h7kxGE2wV_oqGRbqasPqVJN9SiNAEWwzcs645NwPEC48XUK0Q4eUyd9ra_YFv9HGgZ1Yo0gaD0BnRMLxcm-Q",
|
||||
"e": "AQAB",
|
||||
"use": "sig",
|
||||
"kid": "14cc39cd-838d-426d-9bb1-77f3468fba96",
|
||||
"qi": "kly84cu6D3sy64HfRpXfIYuNZTcJxlfdkLcLY-ZHkY5oVUiDBb6VrKwkQq3e5UbxF0a6qzwCk_B0Bn6ChHXLorVLnlx8cUG2TP3C72J_iHpE8Bn3wend7ZqLfcceh19zPOe13352RurPXbewzf1tYVji-OPzJr05fUDrqmesXvI",
|
||||
"dp": "XTZnsbiFDvfNX6Y2mHDr9aDVBeGPTkOs_YAnCBrO7D7ZyI6WUUy8fHWjyxvMCjDS4IZQ5JOPEPRSQuk5BgeElGOoEE0w0-2AOS9Hkbs6G2vv_CdvYNrg2UqZqYA_aSZTMt6xV2JK1Sl59EO7wnJNQaeYe32nA9YeBwAqGoys_Rs",
|
||||
"dq": "GeTJLKLoh2KiZHhXJL3An5ADyC_CganIIfjLs-dPfLJkIXvvisrq1Y4BuvXpDgDtMOTkX7qOUMconM3OMUwGe0lXGfj8eLLhVdZViITcSDE5Lp7TsJEoBQmVbr_Lp1Yxpu56hxenLcY1uOGisCA7f9f_y6LluGewr5dEtwytRyM",
|
||||
"n": "kEVx_IUSr30PMuJTWWg4QYxhOWU80Zl_OKHnGp6PxLqD0wuOmLQv2a0xprzXMIxROl3iYyAY_PQmiLQn4aMR_c55V6N6O_qP5d09tArAipMsVyAICW0RRtJtAL-n9_ktghmYUaVHhq5AXS7flxO2b8KKZWZuKJ1f8clbK16eOJ_-NURjqz90zpuafIA1nzCdNk9AE1NOuXdW81FIjC-82abgDhgyNgNnL33z8BXbwKdog0Hu9BFoyIBXIA8HLzaj-KmyqTY9ewu2JVI8XVLuM_zy-6FmzKGanw0bhZRAFNHc-eraMP0HLJuWf0R9waiKmrPy0i6zISayo4_rm2YJQQ"
|
||||
},
|
||||
{
|
||||
"kty": "EC",
|
||||
"kid": "C6vs25welZOx6WksNYfbMfiw9l96pMnD",
|
||||
"crv": "P-256",
|
||||
"x": "ngLYQnlfF6GsojUwqtcEE3WgTNG2RUlsGhK73RNEl5k",
|
||||
"y": "tKbiDSUSsQ3F1P7wteeHNXIcU-cx6CgSbroeQrQHTLM"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue