diff --git a/java-spiffe-core/src/main/java/spiffe/bundle/x509bundle/X509BundleSet.java b/java-spiffe-core/src/main/java/spiffe/bundle/x509bundle/X509BundleSet.java index 8ab7db5..509559b 100644 --- a/java-spiffe-core/src/main/java/spiffe/bundle/x509bundle/X509BundleSet.java +++ b/java-spiffe-core/src/main/java/spiffe/bundle/x509bundle/X509BundleSet.java @@ -53,7 +53,7 @@ public class X509BundleSet implements X509BundleSource { * @throws BundleNotFoundException if no bundle could be found for the given trust domain */ @Override - public X509Bundle getX509BundleForTrustDomain(final TrustDomain trustDomain) throws BundleNotFoundException { + public X509Bundle getX509BundleForTrustDomain(@NonNull final TrustDomain trustDomain) throws BundleNotFoundException { val bundle = bundles.get(trustDomain); if (bundle == null){ throw new BundleNotFoundException(String.format("No X509 bundle for trust domain %s", trustDomain)); diff --git a/java-spiffe-core/src/main/java/spiffe/internal/CertificateUtils.java b/java-spiffe-core/src/main/java/spiffe/internal/CertificateUtils.java index e0cc8a4..4f94074 100644 --- a/java-spiffe-core/src/main/java/spiffe/internal/CertificateUtils.java +++ b/java-spiffe-core/src/main/java/spiffe/internal/CertificateUtils.java @@ -101,11 +101,16 @@ public class CertificateUtils { * @throws NoSuchAlgorithmException * @throws CertPathValidatorException */ - public static void validate(List chain, List trustedCerts) throws CertificateException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, CertPathValidatorException { + public static void validate(List chain, List trustedCerts) throws CertificateException, CertPathValidatorException { val certificateFactory = getCertificateFactory(); - val pkixParameters = toPkixParameters(trustedCerts); - val certPath = certificateFactory.generateCertPath(chain); - getCertPathValidator().validate(certPath, pkixParameters); + PKIXParameters pkixParameters = null; + try { + pkixParameters = toPkixParameters(trustedCerts); + val certPath = certificateFactory.generateCertPath(chain); + getCertPathValidator().validate(certPath, pkixParameters); + } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException e) { + throw new CertificateException(e); + } } /** @@ -151,28 +156,32 @@ public class CertificateUtils { * * @throws InvalidKeyException if the keys don't match */ - public static void validatePrivateKey(PrivateKey privateKey, X509Certificate x509Certificate) throws InvalidKeyException, NoSuchAlgorithmException, SignatureException { + public static void validatePrivateKey(PrivateKey privateKey, X509Certificate x509Certificate) throws InvalidKeyException { // create a challenge byte[] challenge = new byte[1000]; ThreadLocalRandom.current().nextBytes(challenge); Signature sig = null; - if ("RSA".equals(privateKey.getAlgorithm())) { - sig = Signature.getInstance("SHA256withRSA"); - } else { - sig = Signature.getInstance("SHA1withECDSA"); - } + try { + if ("RSA".equals(privateKey.getAlgorithm())) { + sig = Signature.getInstance("SHA256withRSA"); + } else { + sig = Signature.getInstance("SHA1withECDSA"); + } - sig.initSign(privateKey); - sig.update(challenge); - byte[] signature = sig.sign(); + sig.initSign(privateKey); + sig.update(challenge); + byte[] signature = sig.sign(); - sig.initVerify(x509Certificate.getPublicKey()); - sig.update(challenge); + sig.initVerify(x509Certificate.getPublicKey()); + sig.update(challenge); - if (!sig.verify(signature)) { - throw new InvalidKeyException("Private Key does not match Certificate Public Key"); + if (!sig.verify(signature)) { + throw new InvalidKeyException("Private Key does not match Certificate Public Key"); + } + } catch (SignatureException | NoSuchAlgorithmException e) { + throw new IllegalStateException("Could not validate private keys", e); } } diff --git a/java-spiffe-core/src/main/java/spiffe/spiffeid/SpiffeId.java b/java-spiffe-core/src/main/java/spiffe/spiffeid/SpiffeId.java index 2101d82..2a776d4 100644 --- a/java-spiffe-core/src/main/java/spiffe/spiffeid/SpiffeId.java +++ b/java-spiffe-core/src/main/java/spiffe/spiffeid/SpiffeId.java @@ -58,7 +58,7 @@ public class SpiffeId { throw new IllegalArgumentException("SPIFFE ID cannot be empty"); } - val uri = URI.create(spiffeIdAsString); + val uri = URI.create(normalize(spiffeIdAsString)); if (!SPIFFE_SCHEME.equals(uri.getScheme())) { throw new IllegalArgumentException("Invalid SPIFFE schema"); diff --git a/java-spiffe-core/src/main/java/spiffe/spiffeid/SpiffeIdUtils.java b/java-spiffe-core/src/main/java/spiffe/spiffeid/SpiffeIdUtils.java index 3ddffa6..8a7e29f 100644 --- a/java-spiffe-core/src/main/java/spiffe/spiffeid/SpiffeIdUtils.java +++ b/java-spiffe-core/src/main/java/spiffe/spiffeid/SpiffeIdUtils.java @@ -1,6 +1,7 @@ package spiffe.spiffeid; import lombok.val; +import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.nio.file.Files; @@ -11,6 +12,7 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import static java.util.Collections.EMPTY_LIST; import static org.apache.commons.lang3.StringUtils.isBlank; /** @@ -24,7 +26,8 @@ public class SpiffeIdUtils { * Reads the Accepted SPIFFE IDs from a system property and parses them to {@link SpiffeId} instances. * * @param systemProperty name of the system property that contains a list of SPIFFE IDs separated by a commas. - * @return a list of {@link SpiffeId} parsed from the values read from the security property + * @return a list of {@link SpiffeId} parsed from the values read from the security property, in case there's no values + * in the System property, it returns an emtpy list * * @throws IllegalArgumentException if the given system property is empty or if any of the SPIFFE IDs * cannot be parsed @@ -35,6 +38,9 @@ public class SpiffeIdUtils { } val spiffeIds = System.getProperty(systemProperty); + if (StringUtils.isBlank(spiffeIds)) { + return EMPTY_LIST; + } return toListOfSpiffeIds(spiffeIds, DEFAULT_CHAR_SEPARATOR); } @@ -52,7 +58,12 @@ public class SpiffeIdUtils { if (isBlank(securityProperty)) { throw new IllegalArgumentException("Argument securityProperty cannot be empty"); } + val spiffeIds = Security.getProperty(securityProperty); + if (StringUtils.isBlank(spiffeIds)) { + return EMPTY_LIST; + } + return toListOfSpiffeIds(spiffeIds, DEFAULT_CHAR_SEPARATOR); } @@ -88,7 +99,7 @@ public class SpiffeIdUtils { */ public static List toListOfSpiffeIds(final String spiffeIds, final char separator) { if (isBlank(spiffeIds)) { - throw new IllegalArgumentException("Argument spiffeIds cannot be emtpy"); + throw new IllegalArgumentException("Argument spiffeIds cannot be empty"); } val array = spiffeIds.split(String.valueOf(separator)); diff --git a/java-spiffe-core/src/main/java/spiffe/svid/jwtsvid/JwtSvid.java b/java-spiffe-core/src/main/java/spiffe/svid/jwtsvid/JwtSvid.java index 028c983..84f8d06 100644 --- a/java-spiffe-core/src/main/java/spiffe/svid/jwtsvid/JwtSvid.java +++ b/java-spiffe-core/src/main/java/spiffe/svid/jwtsvid/JwtSvid.java @@ -77,7 +77,7 @@ public class JwtSvid { * when the algorithm is not supported, when the header 'kid' is missing, when the signature cannot be verified, or * when the 'aud' claim has an audience that is not in the audience list provided as parameter * - * @throws IllegalArgumentException when the token cannot be parsed + * @throws IllegalArgumentException when the token is blank or cannot be parsed * * @throws BundleNotFoundException if the bundle for the trust domain of the spiffe id from the 'sub' cannot be found * in the JwtBundleSource @@ -93,6 +93,10 @@ public class JwtSvid { // to find the Authority in the jwtBundleSource. Once the Authority // is found, the token signature is verified + if (StringUtils.isBlank(token)) { + throw new IllegalArgumentException("Token cannot be blank"); + } + Jwt jwt = decodeToken(token); Claims claims = (Claims) jwt.getBody(); List aud = claims.get("aud", List.class); @@ -130,7 +134,11 @@ public class JwtSvid { * the 'aud' has an audience that is not in the audience provided as parameter * @throws IllegalArgumentException when the token cannot be parsed */ - public static JwtSvid parseInsecure(@NonNull final String token, List audience) throws JwtSvidException { + public static JwtSvid parseInsecure(@NonNull final String token, @NonNull List audience) throws JwtSvidException { + if (StringUtils.isBlank(token)) { + throw new IllegalArgumentException("Token cannot be blank"); + + } Jwt jwt = decodeToken(token); Claims claims = (Claims) jwt.getBody(); List aud = claims.get("aud", List.class); @@ -160,7 +168,7 @@ public class JwtSvid { return new Date(expiry.getTime()); } - private static void verifySignature(@NonNull String token, String keyId, PublicKey jwtAuthority) throws JwtSvidException { + private static void verifySignature(String token, String keyId, PublicKey jwtAuthority) throws JwtSvidException { JwtParser jwtParser = Jwts.parserBuilder().setSigningKey(jwtAuthority).build(); try { // parse token with signature verification using the jwt authority (public key) diff --git a/java-spiffe-core/src/main/java/spiffe/svid/x509svid/X509Svid.java b/java-spiffe-core/src/main/java/spiffe/svid/x509svid/X509Svid.java index cdec270..136b54f 100644 --- a/java-spiffe-core/src/main/java/spiffe/svid/x509svid/X509Svid.java +++ b/java-spiffe-core/src/main/java/spiffe/svid/x509svid/X509Svid.java @@ -12,7 +12,6 @@ import java.nio.file.Path; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; -import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; @@ -41,9 +40,9 @@ public class X509Svid implements X509SvidSource { PrivateKey privateKey; private X509Svid( - @NonNull SpiffeId spiffeId, - @NonNull List chain, - @NonNull PrivateKey privateKey) { + SpiffeId spiffeId, + List chain, + PrivateKey privateKey) { this.spiffeId = spiffeId; this.chain = chain; this.privateKey = privateKey; @@ -163,8 +162,6 @@ public class X509Svid implements X509SvidSource { CertificateUtils.validatePrivateKey(privateKey, x509Certificates.get(0)); } catch (InvalidKeyException e) { throw new X509SvidException("Private Key does not match Certificate Public Key", e); - } catch (NoSuchAlgorithmException | SignatureException e) { - throw new IllegalStateException("Could not validate private key", e); } } diff --git a/java-spiffe-core/src/main/java/spiffe/svid/x509svid/X509SvidValidator.java b/java-spiffe-core/src/main/java/spiffe/svid/x509svid/X509SvidValidator.java index 4305cf7..b8a2a3c 100644 --- a/java-spiffe-core/src/main/java/spiffe/svid/x509svid/X509SvidValidator.java +++ b/java-spiffe-core/src/main/java/spiffe/svid/x509svid/X509SvidValidator.java @@ -7,8 +7,6 @@ import spiffe.exception.BundleNotFoundException; import spiffe.internal.CertificateUtils; import spiffe.spiffeid.SpiffeId; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; import java.security.cert.CertPathValidatorException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; @@ -42,8 +40,6 @@ public class X509SvidValidator { CertificateUtils.validate(chain, new ArrayList<>(x509Bundle.getX509Authorities())); } catch (CertPathValidatorException e) { throw new CertificateException("Cert chain cannot be verified", e); - } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException e) { - throw new CertificateException(e.getMessage(), e); } } diff --git a/java-spiffe-core/src/test/java/spiffe/bundle/x509bundle/X509BundleSetTest.java b/java-spiffe-core/src/test/java/spiffe/bundle/x509bundle/X509BundleSetTest.java new file mode 100644 index 0000000..1fccfc3 --- /dev/null +++ b/java-spiffe-core/src/test/java/spiffe/bundle/x509bundle/X509BundleSetTest.java @@ -0,0 +1,135 @@ +package spiffe.bundle.x509bundle; + +import org.junit.jupiter.api.Test; +import spiffe.exception.BundleNotFoundException; +import spiffe.internal.DummyX509Certificate; +import spiffe.spiffeid.TrustDomain; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class X509BundleSetTest { + + @Test + void testOf_listOfBundles_Success() { + X509Bundle x509Bundle1 = new X509Bundle(TrustDomain.of("example.org")); + X509Bundle x509Bundle2 = new X509Bundle(TrustDomain.of("other.org")); + List bundleList = Arrays.asList(x509Bundle1, x509Bundle2); + X509BundleSet bundleSet = X509BundleSet.of(bundleList); + + assertTrue(bundleSet.getBundles().contains(x509Bundle1)); + assertTrue(bundleSet.getBundles().contains(x509Bundle2)); + } + + @Test + void testOf_null_throwsNullPointerException() { + try { + X509BundleSet.of(null); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("bundles is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testAdd() { + X509Bundle x509Bundle1 = new X509Bundle(TrustDomain.of("example.org")); + List bundleList = Collections.singletonList(x509Bundle1); + X509BundleSet bundleSet = X509BundleSet.of(bundleList); + + X509Bundle x509Bundle2 = new X509Bundle(TrustDomain.of("other.org")); + bundleSet.add(x509Bundle2); + + assertTrue(bundleSet.getBundles().contains(x509Bundle1)); + assertTrue(bundleSet.getBundles().contains(x509Bundle2)); + } + + @Test + void testAdd_sameBundleAgain_noDuplicate() { + X509Bundle x509Bundle1 = new X509Bundle(TrustDomain.of("example.org")); + List bundleList = Collections.singletonList(x509Bundle1); + X509BundleSet bundleSet = X509BundleSet.of(bundleList); + + bundleSet.add(x509Bundle1); + + assertTrue(bundleSet.getBundles().contains(x509Bundle1)); + assertEquals(1, bundleSet.getBundles().size()); + } + + @Test + void testAdd_aDifferentBundleForSameTrustDomain_replacesWithNewBundle() { + X509Bundle x509Bundle1 = new X509Bundle(TrustDomain.of("example.org")); + List bundleList = Collections.singletonList(x509Bundle1); + X509BundleSet bundleSet = X509BundleSet.of(bundleList); + + X509Bundle x509Bundle2 = new X509Bundle(TrustDomain.of("example.org")); + x509Bundle2.addX509Authority(new DummyX509Certificate()); + bundleSet.add(x509Bundle2); + + assertTrue(bundleSet.getBundles().contains(x509Bundle2)); + assertFalse(bundleSet.getBundles().contains(x509Bundle1)); + assertEquals(1, bundleSet.getBundles().size()); + } + + @Test + void testAdd_nullBundle_throwsNullPointerException() { + X509Bundle x509Bundle1 = new X509Bundle(TrustDomain.of("example.org")); + List bundleList = Collections.singletonList(x509Bundle1); + X509BundleSet bundleSet = X509BundleSet.of(bundleList); + + try { + bundleSet.add(null); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("x509Bundle is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testGetX509BundleForTrustDomain_Success() throws BundleNotFoundException { + X509Bundle x509Bundle1 = new X509Bundle(TrustDomain.of("example.org")); + X509Bundle x509Bundle2 = new X509Bundle(TrustDomain.of("other.org")); + List bundleList = Arrays.asList(x509Bundle1, x509Bundle2); + X509BundleSet bundleSet = X509BundleSet.of(bundleList); + + assertEquals(x509Bundle1, bundleSet.getX509BundleForTrustDomain(TrustDomain.of("example.org"))); + assertEquals(x509Bundle2, bundleSet.getX509BundleForTrustDomain(TrustDomain.of("other.org"))); + } + + @Test + void testGetX509BundleForTrustDomain_notFoundTrustDomain() { + X509Bundle x509Bundle1 = new X509Bundle(TrustDomain.of("example.org")); + X509Bundle x509Bundle2 = new X509Bundle(TrustDomain.of("other.org")); + List bundleList = Arrays.asList(x509Bundle1, x509Bundle2); + X509BundleSet bundleSet = X509BundleSet.of(bundleList); + + try { + bundleSet.getX509BundleForTrustDomain(TrustDomain.of("unknown.org")); + fail("expected BundleNotFoundException"); + } catch (BundleNotFoundException e) { + assertEquals("No X509 bundle for trust domain unknown.org", e.getMessage()); + } + } + + @Test + void testGetX509BundleForTrustDomain_nullTrustDomain_throwsException() throws BundleNotFoundException { + X509Bundle x509Bundle1 = new X509Bundle(TrustDomain.of("example.org")); + X509Bundle x509Bundle2 = new X509Bundle(TrustDomain.of("other.org")); + List bundleList = Arrays.asList(x509Bundle1, x509Bundle2); + X509BundleSet bundleSet = X509BundleSet.of(bundleList); + + try { + bundleSet.getX509BundleForTrustDomain(null); + fail("expected exception"); + } catch (NullPointerException e) { + assertEquals("trustDomain is marked non-null but is null", e.getMessage()); + } + } + + @Test + void getBundles() { + } +} \ No newline at end of file diff --git a/java-spiffe-core/src/test/java/spiffe/bundle/x509bundle/X509BundleTest.java b/java-spiffe-core/src/test/java/spiffe/bundle/x509bundle/X509BundleTest.java index 3f18046..832bbd8 100644 --- a/java-spiffe-core/src/test/java/spiffe/bundle/x509bundle/X509BundleTest.java +++ b/java-spiffe-core/src/test/java/spiffe/bundle/x509bundle/X509BundleTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.commons.util.StringUtils; +import spiffe.exception.BundleNotFoundException; import spiffe.internal.DummyX509Certificate; import spiffe.spiffeid.TrustDomain; @@ -26,12 +27,42 @@ import static org.junit.jupiter.api.Assertions.*; public class X509BundleTest { @Test - void TestNewBunlde() { + void TestNewBundle() { X509Bundle x509Bundle = new X509Bundle(TrustDomain.of("example.org")); assertEquals(0, x509Bundle.getX509Authorities().size()); assertEquals(TrustDomain.of("example.org"), x509Bundle.getTrustDomain()); } + @Test + void testNewBundle_nullTrustDomain_throwsNullPointerException() { + try { + new X509Bundle(null ); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("trustDomain is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testNewBundleWithAuthorities_nullTrustDomain_throwsNullPointerException() { + try { + new X509Bundle(null, new HashSet<>()); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("trustDomain is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testNewBundleAuthorities_nullAuthorities_throwsNullPointerException() { + try { + new X509Bundle(TrustDomain.of("example.org"), null); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("x509Authorities is marked non-null but is null", e.getMessage()); + } + } + @Test void TestFromAuthorities() { X509Certificate x509Cert1 = new DummyX509Certificate(); @@ -46,10 +77,26 @@ public class X509BundleTest { assertEquals(authorities, x509Bundle.getX509Authorities()); } + @Test + void testGetX509BundleForTrustDomain() throws BundleNotFoundException { + X509Bundle x509Bundle = new X509Bundle(TrustDomain.of("example.org")); + assertEquals(x509Bundle, x509Bundle.getX509BundleForTrustDomain(TrustDomain.of("example.org"))); + } + + @Test + void testGetX509BundleForTrustDomain_notBundleFound_throwsBundleNotFoundException() { + X509Bundle x509Bundle = new X509Bundle(TrustDomain.of("example.org")); + try { + x509Bundle.getX509BundleForTrustDomain(TrustDomain.of("other.org")); + } catch (BundleNotFoundException e) { + assertEquals("No X509 bundle found for trust domain other.org", e.getMessage()); + } + } + @Test void TestLoad_Succeeds() { try { - X509Bundle x509Bundle = X509Bundle.load(TrustDomain.of("example.org"), Paths.get(loadResource("testdata/x509bundle/certs.pem"))); + X509Bundle x509Bundle = X509Bundle.load(TrustDomain.of("example.org"), Paths.get(toUri("testdata/x509bundle/certs.pem"))); assertEquals(2, x509Bundle.getX509Authorities().size()); } catch (IOException | CertificateException | URISyntaxException e) { fail(e); @@ -59,24 +106,64 @@ public class X509BundleTest { @Test void TestLoad_Fails() { try { - X509Bundle x509Bundle = X509Bundle.load(TrustDomain.of("example.org"), Paths.get("testdata/x509bundle/non-existent.pem")); + X509Bundle.load(TrustDomain.of("example.org"), Paths.get("testdata/x509bundle/non-existent.pem")); fail("should have thrown exception"); } catch (IOException | CertificateException e) { assertEquals("Unable to load X.509 bundle file", e.getMessage()); } } + @Test + void testLoad_nullTrustDomain_throwsNullPointerException() throws IOException, CertificateException { + try { + X509Bundle.load(null,Paths.get("testdata/x509bundle/non-existent.pem")); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("trustDomain is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testLoad_nullBundlePath_throwsNullPointerException() throws IOException, CertificateException { + try { + X509Bundle.load(TrustDomain.of("example.org"), null); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("bundlePath is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testParse_nullTrustDomain_throwsNullPointerException() throws IOException, CertificateException { + try { + X509Bundle.parse(null, "bytes".getBytes()); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("trustDomain is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testParse_nullBundlePath_throwsNullPointerException() throws IOException, CertificateException { + try { + X509Bundle.parse(TrustDomain.of("example.org"), null); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("bundleBytes is marked non-null but is null", e.getMessage()); + } + } + @Test void TestX509AuthoritiesCRUD() { X509Bundle bundle1 = null; X509Bundle bundle2 = null; try { // Load bundle1, which contains a single certificate - bundle1 = X509Bundle.load(TrustDomain.of("example.org"), Paths.get(loadResource("testdata/x509bundle/cert.pem"))); + bundle1 = X509Bundle.load(TrustDomain.of("example.org"), Paths.get(toUri("testdata/x509bundle/cert.pem"))); // Load bundle2, which contains 2 certificates // The first certificate is the same than the one used in bundle1 - bundle2 = X509Bundle.load(TrustDomain.of("example.org"), Paths.get(loadResource("testdata/x509bundle/certs.pem"))); + bundle2 = X509Bundle.load(TrustDomain.of("example.org"), Paths.get(toUri("testdata/x509bundle/certs.pem"))); } catch (IOException | CertificateException | URISyntaxException e) { fail(e); } @@ -115,7 +202,7 @@ public class X509BundleTest { @MethodSource("provideX509BundleScenarios") void parseX509Bundle(TestCase testCase) { try { - Path path = Paths.get(loadResource(testCase.path)); + Path path = Paths.get(toUri(testCase.path)); byte[] bytes = Files.readAllBytes(path); X509Bundle x509Bundle = X509Bundle.parse(testCase.trustDomain, bytes); @@ -205,7 +292,7 @@ public class X509BundleTest { } } - private URI loadResource(String path) throws URISyntaxException { + private URI toUri(String path) throws URISyntaxException { return getClass().getClassLoader().getResource(path).toURI(); } } diff --git a/java-spiffe-core/src/test/java/spiffe/internal/CertificateUtilsTest.java b/java-spiffe-core/src/test/java/spiffe/internal/CertificateUtilsTest.java index 79e0320..4d786a1 100644 --- a/java-spiffe-core/src/test/java/spiffe/internal/CertificateUtilsTest.java +++ b/java-spiffe-core/src/test/java/spiffe/internal/CertificateUtilsTest.java @@ -9,8 +9,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Paths; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; import java.security.cert.CertPathValidatorException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; @@ -23,7 +21,7 @@ public class CertificateUtilsTest { @Test void generateCertificates_ofPEMByteArray_returnsListWithOneX509Certificate() throws IOException, URISyntaxException { - val path = Paths.get(loadResource("testdata/internal/cert.pem")); + val path = Paths.get(toUri("testdata/internal/cert.pem")); val certBytes = Files.readAllBytes(path); List x509CertificateList = null; @@ -40,8 +38,8 @@ public class CertificateUtilsTest { @Test void validate_certificateThatIsExpired_throwsCertificateException() throws IOException, CertificateException, URISyntaxException { - val certPath = Paths.get(loadResource("testdata/internal/cert2.pem")); - val certBundle = Paths.get(loadResource("testdata/internal/bundle.pem")); + val certPath = Paths.get(toUri("testdata/internal/cert2.pem")); + val certBundle = Paths.get(toUri("testdata/internal/bundle.pem")); val certBytes = Files.readAllBytes(certPath); val bundleBytes = Files.readAllBytes(certBundle); @@ -52,12 +50,12 @@ public class CertificateUtilsTest { try { CertificateUtils.validate(chain, trustedCert); fail("Expected exception"); - } catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | CertPathValidatorException e) { + } catch (CertPathValidatorException e) { assertEquals("validity check failed", e.getMessage()); } } - private URI loadResource(String path) throws URISyntaxException { + private URI toUri(String path) throws URISyntaxException { return getClass().getClassLoader().getResource(path).toURI(); } } diff --git a/java-spiffe-core/src/test/java/spiffe/spiffeid/SpiffeIdTest.java b/java-spiffe-core/src/test/java/spiffe/spiffeid/SpiffeIdTest.java index 5d5a0c6..eafb0b9 100644 --- a/java-spiffe-core/src/test/java/spiffe/spiffeid/SpiffeIdTest.java +++ b/java-spiffe-core/src/test/java/spiffe/spiffeid/SpiffeIdTest.java @@ -95,9 +95,21 @@ public class SpiffeIdTest { () -> assertEquals("trust-domain.org", spiffeId.getTrustDomain().toString()), () -> assertEquals("/path1/path2", spiffeId.getPath()) ); - } + @Test + void parse_aStringContainingLeadingAndTrailingBlanks_ReturnsASpiffeIdThatHasTrustDomainAndPathSegments() { + val spiffeIdAsString = " spiffe://trust-domain.org/path1/path2 "; + + val spiffeId = SpiffeId.parse(spiffeIdAsString); + + assertAll("SpiffeId", + () -> assertEquals("trust-domain.org", spiffeId.getTrustDomain().toString()), + () -> assertEquals("/path1/path2", spiffeId.getPath()) + ); + } + + @Test void parse_aStringContainingInvalidSchema_throwsIllegalArgumentException() { val invalidadSpiffeId = "siffe://trust-domain.org/path1/path2"; @@ -121,7 +133,27 @@ public class SpiffeIdTest { } @Test - void of_nullTrustDomain_throwsIllegalArgumentException() { + void parse_Null_throwsIllegalArgumentException() { + try { + SpiffeId.parse(null); + fail("Should have thrown IllegalArgumentException"); + } catch (NullPointerException e) { + assertEquals("spiffeIdAsString is marked non-null but is null", e.getMessage()); + } + } + + @Test + void of_nullTrustDomain_throwsNullPointerException() { + try { + SpiffeId.of(null); + fail("Should have thrown IllegalArgumentException"); + } catch (NullPointerException e) { + assertEquals("trustDomain is marked non-null but is null", e.getMessage()); + } + } + + @Test + void of_nullTrustDomainNotNullPath_throwsIllegalArgumentException() { try { SpiffeId.of(null, "path"); fail("Should have thrown IllegalArgumentException"); diff --git a/java-spiffe-core/src/test/java/spiffe/spiffeid/SpiffeIdUtilsTest.java b/java-spiffe-core/src/test/java/spiffe/spiffeid/SpiffeIdUtilsTest.java new file mode 100644 index 0000000..af42b22 --- /dev/null +++ b/java-spiffe-core/src/test/java/spiffe/spiffeid/SpiffeIdUtilsTest.java @@ -0,0 +1,154 @@ +package spiffe.spiffeid; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.Security; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class piffeIdUtilsTest { + + @Test + void getSpiffeIdsFromSystemProperty() { + System.setProperty("spiffe.property", " spiffe://example.org/workload1, spiffe://example.org/workload2 "); + + List spiffeIdList = SpiffeIdUtils.getSpiffeIdsFromSystemProperty("spiffe.property"); + + assertNotNull(spiffeIdList); + assertEquals(2, spiffeIdList.size()); + assertEquals(SpiffeId.parse("spiffe://example.org/workload1"), spiffeIdList.get(0)); + assertEquals(SpiffeId.parse("spiffe://example.org/workload2"), spiffeIdList.get(1)); + } + + @Test + void getSpiffeIdsFromSystemPropertyThatHasNoValue_returnsEmptyList() { + System.setProperty("spiffe.property", ""); + + List spiffeIdList = SpiffeIdUtils.getSpiffeIdsFromSystemProperty("spiffe.property"); + + assertNotNull(spiffeIdList); + assertEquals(0, spiffeIdList.size()); + } + + @Test + void getSpiffeIdsFromBlankSystemProperty_throwsIllegalArgumentException() { + try { + SpiffeIdUtils.getSpiffeIdsFromSystemProperty(""); + fail("should have thrown exception"); + } catch (IllegalArgumentException e) { + //expected + } + } + + @Test + void getSpiffeIdsFromNullSystemProperty_throwsIllegalArgumentException() { + try { + SpiffeIdUtils.getSpiffeIdsFromSystemProperty(null); + fail("should have thrown exception"); + } catch (IllegalArgumentException e) { + //expected + } + } + + @Test + void getSpiffeIdsFromSecurityProperty() { + Security.setProperty("spiffe.property", " spiffe://example.org/workload1, spiffe://example.org/workload2 "); + + List spiffeIdList = SpiffeIdUtils.getSpiffeIdsFromSecurityProperty("spiffe.property"); + + assertNotNull(spiffeIdList); + assertEquals(2, spiffeIdList.size()); + assertEquals(SpiffeId.parse("spiffe://example.org/workload1"), spiffeIdList.get(0)); + assertEquals(SpiffeId.parse("spiffe://example.org/workload2"), spiffeIdList.get(1)); + } + + @Test + void getSpiffeIdsFromSecurityPropertyThatHasNoValue_returnsEmptyList() { + Security.setProperty("spiffe.property", ""); + + List spiffeIdList = SpiffeIdUtils.getSpiffeIdsFromSecurityProperty("spiffe.property"); + + assertNotNull(spiffeIdList); + assertEquals(0, spiffeIdList.size()); + } + + @Test + void getSpiffeIdsFromBlankSecurityProperty_throwsIllegalArgumentException() { + try { + SpiffeIdUtils.getSpiffeIdsFromSecurityProperty(""); + fail("should have thrown exception"); + } catch (IllegalArgumentException e) { + //expected + } + } + + @Test + void getSpiffeIdsFromNullSecurityProperty_throwsIllegalArgumentException() { + try { + SpiffeIdUtils.getSpiffeIdsFromSecurityProperty(null); + fail("should have thrown exception"); + } catch (IllegalArgumentException e) { + //expected + } + } + + @Test + void getSpiffeIdListFromFile() throws URISyntaxException { + Path path = Paths.get(toUri("testdata/spiffeid/spiffeIds.txt")); + + try { + List spiffeIdList = SpiffeIdUtils.getSpiffeIdListFromFile(path); + assertNotNull(spiffeIdList); + assertEquals(3, spiffeIdList.size()); + assertEquals(SpiffeId.parse("spiffe://example.org/workload1"), spiffeIdList.get(0)); + assertEquals(SpiffeId.parse("spiffe://example.org/workload2"), spiffeIdList.get(1)); + assertEquals(SpiffeId.parse("spiffe://example2.org/workload1"), spiffeIdList.get(2)); + } catch (IOException e) { + fail(e); + } + } + + @Test + void getSpiffeIdListFromNonExistenFile_throwsException() throws IOException { + Path path = Paths.get("testdata/spiffeid/non-existent-file"); + + try { + SpiffeIdUtils.getSpiffeIdListFromFile(path); + fail("should have thrown exception"); + } catch (NoSuchFileException e) { + assertEquals("testdata/spiffeid/non-existent-file", e.getMessage()); + } + } + + @Test + void toListOfSpiffeIds() { + String spiffeIdsAsString = " spiffe://example.org/workload1, spiffe://example.org/workload2 "; + + List spiffeIdList = SpiffeIdUtils.toListOfSpiffeIds(spiffeIdsAsString, ','); + + assertNotNull(spiffeIdList); + assertEquals(2, spiffeIdList.size()); + assertEquals(SpiffeId.parse("spiffe://example.org/workload1"), spiffeIdList.get(0)); + assertEquals(SpiffeId.parse("spiffe://example.org/workload2"), spiffeIdList.get(1)); + } + + @Test + void toListOfSPiffeIds_blankStringParameter() { + try { + SpiffeIdUtils.toListOfSpiffeIds("", ','); + } catch (IllegalArgumentException e) { + assertEquals("Argument spiffeIds cannot be empty", e.getMessage()); + } + } + + private URI toUri(String path) throws URISyntaxException { + return getClass().getClassLoader().getResource(path).toURI(); + } +} \ No newline at end of file diff --git a/java-spiffe-core/src/test/java/spiffe/svid/jwtsvid/JwtSvidParseAndValidateTest.java b/java-spiffe-core/src/test/java/spiffe/svid/jwtsvid/JwtSvidParseAndValidateTest.java index 6a539eb..44866aa 100644 --- a/java-spiffe-core/src/test/java/spiffe/svid/jwtsvid/JwtSvidParseAndValidateTest.java +++ b/java-spiffe-core/src/test/java/spiffe/svid/jwtsvid/JwtSvidParseAndValidateTest.java @@ -7,6 +7,7 @@ import io.jsonwebtoken.impl.DefaultClaims; import io.jsonwebtoken.security.Keys; import lombok.Builder; import lombok.Value; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -34,7 +35,7 @@ class JwtSvidParseAndValidateTest { @ParameterizedTest @MethodSource("provideJwtScenarios") - void parseJwt(TestCase testCase) { + void parseAndValidateJwt(TestCase testCase) { try { String token = testCase.generateToken.get(); @@ -44,13 +45,61 @@ class JwtSvidParseAndValidateTest { assertEquals(testCase.expectedJwtSvid.getAudience(), jwtSvid.getAudience()); assertEquals(testCase.expectedJwtSvid.getExpiry().toInstant().getEpochSecond(), jwtSvid.getExpiry().toInstant().getEpochSecond()); assertEquals(token, jwtSvid.getToken()); + assertEquals(token, jwtSvid.marshall()); } catch (Exception e) { assertEquals(testCase.expectedException.getClass(), e.getClass()); assertEquals(testCase.expectedException.getMessage(), e.getMessage()); } - } + @Test + void testParseAndValidate_nullToken_throwsNullPointerException() throws JwtSvidException, AuthorityNotFoundException, BundleNotFoundException { + TrustDomain trustDomain = TrustDomain.of("test.domain"); + JwtBundle jwtBundle = new JwtBundle(trustDomain); + List audience = Collections.singletonList("audience"); + + try { + JwtSvid.parseAndValidate(null, jwtBundle, audience); + } catch (NullPointerException e) { + assertEquals("token is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testParseAndValidate_emptyToken_throwsIllegalArgumentException() throws JwtSvidException, AuthorityNotFoundException, BundleNotFoundException { + TrustDomain trustDomain = TrustDomain.of("test.domain"); + JwtBundle jwtBundle = new JwtBundle(trustDomain); + List audience = Collections.singletonList("audience"); + + try { + JwtSvid.parseAndValidate("", jwtBundle, audience); + } catch (IllegalArgumentException e) { + assertEquals("Token cannot be blank", e.getMessage()); + } + } + + @Test + void testParseAndValidate_nullBundle_throwsNullPointerException() throws JwtSvidException, AuthorityNotFoundException, BundleNotFoundException { + List audience = Collections.singletonList("audience"); + try { + JwtSvid.parseAndValidate("token", null, audience); + } catch (NullPointerException e) { + assertEquals("jwtBundleSource is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testParseAndValidate_nullAudience_throwsNullPointerException() throws JwtSvidException, AuthorityNotFoundException, BundleNotFoundException { + TrustDomain trustDomain = TrustDomain.of("test.domain"); + JwtBundle jwtBundle = new JwtBundle(trustDomain); + List audience = Collections.singletonList("audience"); + + try { + JwtSvid.parseAndValidate("token", jwtBundle, null); + } catch (NullPointerException e) { + assertEquals("audience is marked non-null but is null", e.getMessage()); + } + } static Stream provideJwtScenarios() { KeyPair key1 = Keys.keyPairFor(SignatureAlgorithm.ES384); diff --git a/java-spiffe-core/src/test/java/spiffe/svid/jwtsvid/JwtSvidParseInsecureTest.java b/java-spiffe-core/src/test/java/spiffe/svid/jwtsvid/JwtSvidParseInsecureTest.java index a0712c6..cd6c54b 100644 --- a/java-spiffe-core/src/test/java/spiffe/svid/jwtsvid/JwtSvidParseInsecureTest.java +++ b/java-spiffe-core/src/test/java/spiffe/svid/jwtsvid/JwtSvidParseInsecureTest.java @@ -7,6 +7,7 @@ import io.jsonwebtoken.impl.DefaultClaims; import io.jsonwebtoken.security.Keys; import lombok.Builder; import lombok.Value; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -49,6 +50,42 @@ class JwtSvidParseInsecureTest { } + @Test + void testParseInsecure_nullToken_throwsNullPointerException() throws JwtSvidException { + List audience = Collections.singletonList("audience"); + + try { + JwtSvid.parseInsecure(null, audience); + } catch (NullPointerException e) { + assertEquals("token is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testParseAndValidate_emptyToken_throwsIllegalArgumentException() throws JwtSvidException { + List audience = Collections.singletonList("audience"); + try { + JwtSvid.parseInsecure("", audience); + } catch (IllegalArgumentException e) { + assertEquals("Token cannot be blank", e.getMessage()); + } + } + + @Test + void testParseInsecure_nullAudience_throwsNullPointerException() throws JwtSvidException { + try { + KeyPair key1 = Keys.keyPairFor(SignatureAlgorithm.ES384); + TrustDomain trustDomain = TrustDomain.of("test.domain"); + SpiffeId spiffeId = trustDomain.newSpiffeId("host"); + List audience = Collections.singletonList("audience"); + Date expiration = new Date(System.currentTimeMillis() + 3600000); + Claims claims = buildClaims(audience, spiffeId.toString(), expiration); + JwtSvid.parseInsecure(generateToken(claims, key1, "authority1"), null); + } catch (NullPointerException e) { + assertEquals("audience is marked non-null but is null", e.getMessage()); + } + } + static Stream provideJwtScenarios() { KeyPair key1 = Keys.keyPairFor(SignatureAlgorithm.ES384); diff --git a/java-spiffe-core/src/test/java/spiffe/svid/x509svid/X509SvidTest.java b/java-spiffe-core/src/test/java/spiffe/svid/x509svid/X509SvidTest.java index 3895e7e..4b87a73 100644 --- a/java-spiffe-core/src/test/java/spiffe/svid/x509svid/X509SvidTest.java +++ b/java-spiffe-core/src/test/java/spiffe/svid/x509svid/X509SvidTest.java @@ -16,6 +16,7 @@ import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.security.cert.X509Certificate; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; @@ -38,8 +39,8 @@ public class X509SvidTest { @Test void testLoad_Success() throws URISyntaxException { - Path certPath = Paths.get(loadResource(certSingle)); - Path keyPath = Paths.get(loadResource(keyRSA)); + Path certPath = Paths.get(toUri(certSingle)); + Path keyPath = Paths.get(toUri(keyRSA)); try { X509Svid x509Svid = X509Svid.load(certPath, keyPath); assertEquals("spiffe://example.org/workload-1", x509Svid.getSpiffeId().toString()); @@ -50,7 +51,7 @@ public class X509SvidTest { @Test void testLoad_FailsCannotReadCertFile() throws URISyntaxException { - Path keyPath = Paths.get(loadResource(keyRSA)); + Path keyPath = Paths.get(toUri(keyRSA)); try { X509Svid.load(Paths.get("not-existent-cert"), keyPath); fail("should have thrown IOException"); @@ -61,7 +62,7 @@ public class X509SvidTest { @Test void testLoad_FailsCannotReadKeyFile() throws URISyntaxException { - Path certPath = Paths.get(loadResource(certSingle)); + Path certPath = Paths.get(toUri(certSingle)); try { X509Svid.load(certPath, Paths.get("not-existent-key")); fail("should have thrown IOException"); @@ -70,13 +71,72 @@ public class X509SvidTest { } } + @Test + void testLoad_nullCertFilePath_throwsNullPointerException() throws URISyntaxException { + try { + X509Svid.load(null, Paths.get(toUri(keyRSA))); + fail("should have thrown exception"); + } catch (NullPointerException | X509SvidException e) { + assertEquals("certsFilePath is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testLoad_nullKeyFilePath_throwsNullPointerException() throws URISyntaxException, X509SvidException { + try { + X509Svid.load(Paths.get(toUri(certSingle)), null); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("privateKeyFilePath is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testParse_nullByteArray_throwsNullPointerException() throws X509SvidException { + try { + X509Svid.parse(null, "key".getBytes()); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("certsBytes is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testParse_nullKeyByteArray_throwsNullPointerException() throws X509SvidException { + try { + X509Svid.parse("cert".getBytes(), null); + fail("should have thrown exception"); + } catch (NullPointerException e) { + assertEquals("privateKeyBytes is marked non-null but is null", e.getMessage()); + } + } + + @Test + void testGetX509Svid() throws URISyntaxException, X509SvidException { + Path certPath = Paths.get(toUri(certSingle)); + Path keyPath = Paths.get(toUri(keyRSA)); + X509Svid x509Svid = X509Svid.load(certPath, keyPath); + assertEquals(x509Svid, x509Svid.getX509Svid()); + } + + @Test + void testGetChainArray() throws URISyntaxException, X509SvidException { + Path certPath = Paths.get(toUri(certMultiple)); + Path keyPath = Paths.get(toUri(keyECDSA)); + X509Svid x509Svid = X509Svid.load(certPath, keyPath); + X509Certificate[] x509CertificatesArray = x509Svid.getChainArray(); + assertEquals(x509Svid.getChain().get(0), x509CertificatesArray[0]); + assertEquals(x509Svid.getChain().get(1), x509CertificatesArray[1]); + } + + @ParameterizedTest @MethodSource("provideX509SvidScenarios") void parseX509Svid(TestCase testCase) { try { - Path certPath = Paths.get(loadResource(testCase.certsPath)); - Path keyPath = Paths.get(loadResource(testCase.keyPath)); + Path certPath = Paths.get(toUri(testCase.certsPath)); + Path keyPath = Paths.get(toUri(testCase.keyPath)); byte[] certBytes = Files.readAllBytes(certPath); byte[] keyBytes = Files.readAllBytes(keyPath); @@ -246,7 +306,7 @@ public class X509SvidTest { } } - private URI loadResource(String path) throws URISyntaxException { + private URI toUri(String path) throws URISyntaxException { return getClass().getClassLoader().getResource(path).toURI(); } } diff --git a/java-spiffe-core/src/test/java/spiffe/svid/x509svid/X509SvidValidatorTest.java b/java-spiffe-core/src/test/java/spiffe/svid/x509svid/X509SvidValidatorTest.java index 2e969d1..0eacb4c 100644 --- a/java-spiffe-core/src/test/java/spiffe/svid/x509svid/X509SvidValidatorTest.java +++ b/java-spiffe-core/src/test/java/spiffe/svid/x509svid/X509SvidValidatorTest.java @@ -21,6 +21,7 @@ import java.security.cert.CertificateException; import java.util.Arrays; import java.util.List; +import static java.util.Collections.EMPTY_LIST; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.when; @@ -37,11 +38,11 @@ public class X509SvidValidatorTest { @Test void verifyChain_certificateExpired_throwsCertificateException() throws IOException, CertificateException, BundleNotFoundException, URISyntaxException { - val certPath = Paths.get(loadResource("testdata/x509svid/cert.pem")); + val certPath = Paths.get(toUri("testdata/x509svid/cert.pem")); val certBytes = Files.readAllBytes(certPath); val chain = CertificateUtils.generateCertificates(certBytes); - val bundlePath = Paths.get(loadResource("testdata/x509svid/bundle.pem")); + val bundlePath = Paths.get(toUri("testdata/x509svid/bundle.pem")); X509Bundle x509Bundle= X509Bundle.load( TrustDomain.of("example.org"), @@ -63,11 +64,11 @@ public class X509SvidValidatorTest { @Test void verifyChain_noBundleForTrustDomain_throwsBundleNotFoundException() throws IOException, CertificateException, BundleNotFoundException, URISyntaxException { - val certPath = Paths.get(loadResource("testdata/x509svid/cert.pem")); + val certPath = Paths.get(toUri("testdata/x509svid/cert.pem")); val certBytes = Files.readAllBytes(certPath); val chain = CertificateUtils.generateCertificates(certBytes); - val bundlePath = Paths.get(loadResource("testdata/x509svid/bundle.pem")); + val bundlePath = Paths.get(toUri("testdata/x509svid/bundle.pem")); X509Bundle x509Bundle= X509Bundle.load( TrustDomain.of("example.org"), @@ -92,7 +93,7 @@ public class X509SvidValidatorTest { val spiffeId1 = SpiffeId.parse("spiffe://example.org/test"); val spiffeId2 = SpiffeId.parse("spiffe://example.org/test2"); - val certPath = Paths.get(loadResource("testdata/x509svid/cert.pem")); + val certPath = Paths.get(toUri("testdata/x509svid/cert.pem")); val certBytes = Files.readAllBytes(certPath); val x509Certificate = CertificateUtils.generateCertificates(certBytes); @@ -107,7 +108,7 @@ public class X509SvidValidatorTest { val spiffeId2 = SpiffeId.parse("spiffe://example.org/other2"); List spiffeIdList = Arrays.asList(spiffeId1, spiffeId2); - val certPath = Paths.get(loadResource("testdata/x509svid/cert.pem")); + val certPath = Paths.get(toUri("testdata/x509svid/cert.pem")); val certBytes = Files.readAllBytes(certPath); val x509Certificate = CertificateUtils.generateCertificates(certBytes); @@ -119,7 +120,53 @@ public class X509SvidValidatorTest { } } - private URI loadResource(String path) throws URISyntaxException { + @Test + void checkSpiffeId_nullX509Certificate_throwsNullPointerException() throws CertificateException { + try { + X509SvidValidator.verifySpiffeId(null, () -> EMPTY_LIST); + fail("should have thrown an exception"); + } catch (NullPointerException e) { + assertEquals("x509Certificate is marked non-null but is null", e.getMessage()); + } + } + + @Test + void checkSpiffeId_nullAcceptedSpiffeIdsSuppplier_throwsNullPointerException() throws CertificateException, URISyntaxException, IOException { + try { + val certPath = Paths.get(toUri("testdata/x509svid/cert.pem")); + val certBytes = Files.readAllBytes(certPath); + val x509Certificate = CertificateUtils.generateCertificates(certBytes); + X509SvidValidator.verifySpiffeId(x509Certificate.get(0), null); + fail("should have thrown an exception"); + } catch (NullPointerException e) { + assertEquals("acceptedSpiffedIdsSupplier is marked non-null but is null", e.getMessage()); + } + } + + @Test + void verifyChain_nullChain_throwsNullPointerException() throws CertificateException, BundleNotFoundException { + try { + X509SvidValidator.verifyChain(null, bundleSourceMock); + fail("should have thrown an exception"); + } catch (NullPointerException e) { + assertEquals("chain is marked non-null but is null", e.getMessage()); + } + } + + @Test + void verifyChain_nullBundleSource_throwsNullPointerException() throws CertificateException, BundleNotFoundException, URISyntaxException, IOException { + try { + val certPath = Paths.get(toUri("testdata/x509svid/cert.pem")); + val certBytes = Files.readAllBytes(certPath); + val chain = CertificateUtils.generateCertificates(certBytes); + X509SvidValidator.verifyChain(chain, null); + fail("should have thrown an exception"); + } catch (NullPointerException e) { + assertEquals("x509BundleSource is marked non-null but is null", e.getMessage()); + } + } + + private URI toUri(String path) throws URISyntaxException { return getClass().getClassLoader().getResource(path).toURI(); } } diff --git a/java-spiffe-core/src/test/resources/testdata/spiffeid/spiffeIds.txt b/java-spiffe-core/src/test/resources/testdata/spiffeid/spiffeIds.txt new file mode 100644 index 0000000..f293245 --- /dev/null +++ b/java-spiffe-core/src/test/resources/testdata/spiffeid/spiffeIds.txt @@ -0,0 +1,3 @@ +spiffe://example.org/workload1 +spiffe://example.org/workload2 +spiffe://example2.org/workload1 diff --git a/java-spiffe-helper/src/test/java/spiffe/helper/KeyStoreTest.java b/java-spiffe-helper/src/test/java/spiffe/helper/KeyStoreTest.java index 9e2dc70..411fa5e 100644 --- a/java-spiffe-helper/src/test/java/spiffe/helper/KeyStoreTest.java +++ b/java-spiffe-helper/src/test/java/spiffe/helper/KeyStoreTest.java @@ -38,8 +38,8 @@ public class KeyStoreTest { void setup() throws X509SvidException, URISyntaxException { x509Svid = X509Svid .load( - Paths.get(loadResource("testdata/x509cert.pem")), - Paths.get(loadResource("testdata/pkcs8key.pem")) + Paths.get(toUri("testdata/x509cert.pem")), + Paths.get(toUri("testdata/pkcs8key.pem")) ); } @@ -97,7 +97,7 @@ public class KeyStoreTest { } } - private URI loadResource(String path) throws URISyntaxException { + private URI toUri(String path) throws URISyntaxException { return getClass().getClassLoader().getResource(path).toURI(); } } diff --git a/java-spiffe-provider/src/test/java/spiffe/provider/SpiffeKeyManagerTest.java b/java-spiffe-provider/src/test/java/spiffe/provider/SpiffeKeyManagerTest.java index 86743e1..fc1cc9c 100644 --- a/java-spiffe-provider/src/test/java/spiffe/provider/SpiffeKeyManagerTest.java +++ b/java-spiffe-provider/src/test/java/spiffe/provider/SpiffeKeyManagerTest.java @@ -34,8 +34,8 @@ public class SpiffeKeyManagerTest { keyManager = (X509KeyManager) new SpiffeKeyManagerFactory().engineGetKeyManagers(x509SvidSource)[0]; x509Svid = X509Svid .load( - Paths.get(loadResource("testdata/cert.pem")), - Paths.get(loadResource("testdata/key.pem"))); + Paths.get(toUri("testdata/cert.pem")), + Paths.get(toUri("testdata/key.pem"))); } @Test @@ -60,7 +60,7 @@ public class SpiffeKeyManagerTest { assertNotNull(privateKey); } - private URI loadResource(String path) throws URISyntaxException { + private URI toUri(String path) throws URISyntaxException { return getClass().getClassLoader().getResource(path).toURI(); } } diff --git a/java-spiffe-provider/src/test/java/spiffe/provider/SpiffeTrustManagerTest.java b/java-spiffe-provider/src/test/java/spiffe/provider/SpiffeTrustManagerTest.java index 2d39520..4d275a0 100644 --- a/java-spiffe-provider/src/test/java/spiffe/provider/SpiffeTrustManagerTest.java +++ b/java-spiffe-provider/src/test/java/spiffe/provider/SpiffeTrustManagerTest.java @@ -43,16 +43,16 @@ public class SpiffeTrustManagerTest { static void setupClass() throws IOException, CertificateException, X509SvidException, URISyntaxException { x509Svid = X509Svid .load( - Paths.get(loadResource("testdata/cert.pem")), - Paths.get(loadResource("testdata/key.pem"))); + Paths.get(toUri("testdata/cert.pem")), + Paths.get(toUri("testdata/key.pem"))); otherX509Svid = X509Svid .load( - Paths.get(loadResource("testdata/cert2.pem")), - Paths.get(loadResource("testdata/key2.pem"))); + Paths.get(toUri("testdata/cert2.pem")), + Paths.get(toUri("testdata/key2.pem"))); x509Bundle = X509Bundle .load( TrustDomain.of("example.org"), - Paths.get(loadResource("testdata/bundle.pem"))); + Paths.get(toUri("testdata/bundle.pem"))); } @BeforeEach @@ -206,7 +206,7 @@ public class SpiffeTrustManagerTest { } } - private static URI loadResource(String path) throws URISyntaxException { + private static URI toUri(String path) throws URISyntaxException { return SpiffeTrustManagerTest.class.getClassLoader().getResource(path).toURI(); } }