Skip to content

Commit

Permalink
Merge pull request #854 from sigstore/more_tuf_tests
Browse files Browse the repository at this point in the history
Add tests for downloadTarget
  • Loading branch information
loosebazooka authored Dec 5, 2024
2 parents abd0524 + ecfcccd commit e887c23
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
public class FileSystemTufStore implements MetaStore, TargetStore {

private final Path repoBaseDir;
private final Path targetsCache;
private final Path targetsDir;

@VisibleForTesting
FileSystemTufStore(Path repoBaseDir, Path targetsCache) {
FileSystemTufStore(Path repoBaseDir, Path targetsDir) {
this.repoBaseDir = repoBaseDir;
this.targetsCache = targetsCache;
this.targetsDir = targetsDir;
}

public static FileSystemTufStore newFileSystemStore(Path repoBaseDir) throws IOException {
Expand All @@ -62,19 +62,19 @@ public static FileSystemTufStore newFileSystemStore(Path repoBaseDir, Path targe

@Override
public String getIdentifier() {
return "Meta: " + repoBaseDir.toAbsolutePath() + ", Targets:" + targetsCache.toAbsolutePath();
return "Meta: " + repoBaseDir.toAbsolutePath() + ", Targets:" + targetsDir.toAbsolutePath();
}

@Override
public void writeTarget(String targetName, byte[] targetContents) throws IOException {
var encoded = URLEncoder.encode(targetName, StandardCharsets.UTF_8);
Files.write(targetsCache.resolve(encoded), targetContents);
Files.write(targetsDir.resolve(encoded), targetContents);
}

@Override
public byte[] readTarget(String targetName) throws IOException {
var encoded = URLEncoder.encode(targetName, StandardCharsets.UTF_8);
return Files.readAllBytes(targetsCache.resolve(encoded));
return Files.readAllBytes(targetsDir.resolve(encoded));
}

@Override
Expand Down Expand Up @@ -106,4 +106,12 @@ public void clearMeta(String role) throws IOException {
Files.delete(metaFile);
}
}

public Path getRepoBaseDir() {
return repoBaseDir;
}

public Path getTargetsDir() {
return targetsDir;
}
}
90 changes: 56 additions & 34 deletions sigstore-java/src/test/java/dev/sigstore/tuf/UpdaterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,11 @@
import io.github.netmikey.logunit.api.LogCapturer;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
Expand Down Expand Up @@ -119,8 +117,7 @@ static void startRemoteResourceServer() throws Exception {
}

@Test
public void testRootUpdate_notEnoughSignatures()
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
public void testRootUpdate_notEnoughSignatures() throws Exception {
setupMirror("synthetic/root-unsigned", "2.root.json");
var updater = createTimeStaticUpdater(localStorePath, UPDATER_SYNTHETIC_TRUSTED_ROOT);
try {
Expand Down Expand Up @@ -453,8 +450,7 @@ public void testTargetsUpdate_targetExpired() throws Exception {
}

@Test
public void testTargetsUpdate_success()
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
public void testTargetsUpdate_success() throws Exception {
setupMirror(
"synthetic/test-template",
"2.root.json",
Expand Down Expand Up @@ -495,8 +491,7 @@ public void testTargetsDownload_targetMissingTargetMetadata() throws Exception {
}

@Test
public void testTargetsDownload_targetFileNotFound()
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
public void testTargetsDownload_targetFileNotFound() throws Exception {
setupMirror(
"synthetic/test-template",
"2.root.json",
Expand All @@ -512,8 +507,7 @@ public void testTargetsDownload_targetFileNotFound()
}

@Test
public void testTargetsDownload_targetInvalidLength()
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
public void testTargetsDownload_targetInvalidLength() throws Exception {
setupMirror(
"synthetic/targets-download-invalid-length",
"2.root.json",
Expand All @@ -530,8 +524,7 @@ public void testTargetsDownload_targetInvalidLength()
}

@Test
public void testTargetsDownload_targetFileInvalidHash()
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
public void testTargetsDownload_targetFileInvalidHash() throws Exception {
setupMirror(
"synthetic/targets-download-invalid-hash",
"2.root.json",
Expand Down Expand Up @@ -585,6 +578,53 @@ public void testTargetsDownload_sha256Only() throws Exception {
assertDoesNotThrow(updater::update);
}

@Test
public void testDownloadTarget_singleTarget() throws Exception {
setupMirror(
"synthetic/test-template",
"2.root.json",
"timestamp.json",
"3.snapshot.json",
"3.targets.json",
"targets/860de8f9a858eea7190fcfa1b53fe55914d3c38f17f8f542273012d19cc9509bb423f37b7c13c577a56339ad7f45273b479b1d0df837cb6e20a550c27cce0885.test.txt",
"targets/32005f02eac21b4cf161a02495330b6c14b548622b5f7e19d59ecfa622de650603ecceea39ed86cc322749a813503a72ad14ce5462c822b511eaf2f2cd2ad8f2.test.txt.v2",
"targets/53904bc6216230bf8da0ec42d34004a3f36764de698638641870e37d270e4fd13e1079285f8bca73c2857a279f6f7fbc82038274c3eb48ec5bb2da9b2e30491a.test2.txt");
var updater = createTimeStaticUpdater(localStorePath, UPDATER_SYNTHETIC_TRUSTED_ROOT);
updater.updateMeta();
updater.downloadTarget("test.txt");
Assertions.assertEquals(1, countFilesInTargetsDir(updater));
updater.downloadTarget("test2.txt");
Assertions.assertEquals(2, countFilesInTargetsDir(updater));
}

@Test
public void testDownloadTarget_inSubDirectory() throws Exception {
var root =
Path.of(
Resources.getResource("dev/sigstore/tuf/synthetic/targets-with-subdirs/root.json")
.getPath());
setupMirror(
"synthetic/targets-with-subdirs",
"1.root.json",
"timestamp.json",
"1.snapshot.json",
"1.targets.json",
"targets/subdir/860de8f9a858eea7190fcfa1b53fe55914d3c38f17f8f542273012d19cc9509bb423f37b7c13c577a56339ad7f45273b479b1d0df837cb6e20a550c27cce0885.test.txt");
var updater = createTimeStaticUpdater(localStorePath, root);
updater.updateMeta();
updater.downloadTarget("subdir/test.txt");
Assertions.assertEquals(1, countFilesInTargetsDir(updater));
}

private long countFilesInTargetsDir(Updater updater) throws IOException {
try (var filesStream =
Files.list(((FileSystemTufStore) updater.getTargetStore()).getTargetsDir())) {
return filesStream.count();
} catch (UncheckedIOException ex) {
throw ex.getCause();
}
}

private static final byte[] TEST_HASH_VERIFYIER_BYTES =
"testdata".getBytes(StandardCharsets.UTF_8);
private static final String GOOD_256_HASH =
Expand Down Expand Up @@ -737,8 +777,7 @@ private void bootstrapLocalStore(
"04cc1cd53a61c23e88cc54b488dfae168a257c34fac3e88811c55962b24cffbfecb724447999c54670e365883716302e49da57c79a33cd3e16f81fbc66f0bcdf48"));

@Test
public void testVerifyDelegate_verified()
throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, IOException {
public void testVerifyDelegate_verified() throws Exception {
List<Signature> sigs = ImmutableList.of(SIG_1, SIG_2);

Map<String, Key> publicKeys =
Expand Down Expand Up @@ -800,8 +839,7 @@ public void testVerifyDelegate_belowThreshold() throws Exception {

// Just testing boundary conditions for iteration bugs.
@Test
public void testVerifyDelegate_emptyLists()
throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, IOException {
public void testVerifyDelegate_emptyLists() throws Exception {
List<Signature> sigs = ImmutableList.of();

Map<String, Key> publicKeys = ImmutableMap.of();
Expand All @@ -821,8 +859,7 @@ public void testVerifyDelegate_emptyLists()
}

@Test
public void testVerifyDelegate_goodSigsAndKeysButNotInRole()
throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, IOException {
public void testVerifyDelegate_goodSigsAndKeysButNotInRole() throws Exception {
List<Signature> sigs = ImmutableList.of(SIG_1, SIG_2);

Map<String, Key> publicKeys =
Expand Down Expand Up @@ -931,21 +968,6 @@ private static void setupMirror(String repoName, String... files) throws IOExcep
TestResources.setupRepoFiles(repoName, localMirrorPath, files);
}

private void assertRootNotExpired(Root root) {
assertTrue(
root.getSignedMeta()
.getExpiresAsDate()
.isAfter(ZonedDateTime.parse(TEST_STATIC_UPDATE_TIME)),
"The root should not be expired passed test static update time: "
+ TEST_STATIC_UPDATE_TIME);
}

private void assertRootVersionIncreased(Root oldRoot, Root newRoot) throws IOException {
assertTrue(
oldRoot.getSignedMeta().getVersion() <= newRoot.getSignedMeta().getVersion(),
"The new root version should be higher than the old root.");
}

private void assertStoreContains(String resource) {
assertTrue(
localStorePath.resolve(resource).toFile().exists(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"signed":{"_type":"root","spec_version":"1.0","version":1,"expires":"2025-02-18T18:35:54Z","keys":{"32ebeea523ee901ac346018dc416e153e399a9c5a337c9197e55962bf75884db":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5RfvOGyg9WsH7ss0fLE/ugmvIFIa\nzpHIEPhk4m2WPG1UVrxgIZVJQdIqOwEx9dRGVIJJb3mKBIYv4VKMBCUgfg==\n-----END PUBLIC KEY-----\n"}},"3332a046bd204e13b3c749c87179351a5b5fbf20735b37137d9694835a846c42":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK9TCGwshxW1d+pPkHt9pMLab9AZZ\n2ovDuLHI561zAhgh+5PxPvCSZc/KVzFXK854qltuh2nhVgoAJya40p6yew==\n-----END PUBLIC KEY-----\n"}},"54461f997d405cd03a912649b306f349412dc9ef2e475a89a1f18981e1a2cf5e":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPcRd5DQoGtZIEPgzUnrIHPeMUpb0\nDG4HepKiiFavuZ43kPBMl77XEXP3Fmvj650uahsqLnhrjIljkQEra41waw==\n-----END PUBLIC KEY-----\n"}},"97b9f13f07972ce34e386ca1fc74fa1f293ca9b1b23c23b1da178a31e8b77d0b":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsoSjUEAYDjgUt4jikGNdUN9bVWSz\nTCohcyDKwCCDr1rfStHF8m8ommeFfiTyYtTGdNGtdyMv4wsqLs+CVFXXKg==\n-----END PUBLIC KEY-----\n"}},"f944fd2f09223b2d8a7f7673bb31f625ed12026fb6d2a4c251a3cfd6e43f9119":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEToq4xkfD1+vpPCyeAft/GKmNOb5J\nQzBiNnle6envv61RXZ0+Zv+6RLL/GpMYJ3GQnDwz3vQ2KTT2SNbtiHlWiA==\n-----END PUBLIC KEY-----\n"}}},"roles":{"root":{"keyids":["32ebeea523ee901ac346018dc416e153e399a9c5a337c9197e55962bf75884db","54461f997d405cd03a912649b306f349412dc9ef2e475a89a1f18981e1a2cf5e"],"threshold":1},"snapshot":{"keyids":["f944fd2f09223b2d8a7f7673bb31f625ed12026fb6d2a4c251a3cfd6e43f9119"],"threshold":1},"targets":{"keyids":["97b9f13f07972ce34e386ca1fc74fa1f293ca9b1b23c23b1da178a31e8b77d0b"],"threshold":1},"timestamp":{"keyids":["3332a046bd204e13b3c749c87179351a5b5fbf20735b37137d9694835a846c42"],"threshold":1}},"consistent_snapshot":true},"signatures":[{"keyid":"32ebeea523ee901ac346018dc416e153e399a9c5a337c9197e55962bf75884db","sig":"3045022100cd1606f8a435c67277ba5afc61d7c48a2cf5c3f9433a3547fc4a8a3228711d50022047492c1bb08cb999c8525536e2822ac46a44bd69c91217655499814012ff3f1a"},{"keyid":"54461f997d405cd03a912649b306f349412dc9ef2e475a89a1f18981e1a2cf5e","sig":"304502205a37d21f635b8616dfeb0fd65459896efc13b2de9442b9fc5a8279696c0acc0d022100996988b3f2e26bc2fe352d89162a532e81123c6be4f7bfcf72300898d845c547"}]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"signed":{"_type":"snapshot","spec_version":"1.0","version":1,"expires":"2025-01-19T18:36:49Z","meta":{"targets.json":{"length":532,"hashes":{"sha512":"53d5256dd4926de0b79662f0d911ed42a2dd19c6480bce690199ac2eec9228aa97f5e3709746ef615d6dd758115d221790bbc7e4976907f62fc742a7406a0062"},"version":1}}},"signatures":[{"keyid":"f944fd2f09223b2d8a7f7673bb31f625ed12026fb6d2a4c251a3cfd6e43f9119","sig":"3046022100cfdb316b9407245c20f3b4ebe24cbc524e5324e1ceadd7ba0298384d8218ec76022100a596bc5912fa9a78fab28223d5bb36b7667dfa3ca5f63017eddcf9b427990b24"}]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"signed":{"_type":"targets","spec_version":"1.0","version":1,"expires":"2025-02-20T18:36:39Z","targets":{"subdir/test.txt":{"length":10,"hashes":{"sha512":"860de8f9a858eea7190fcfa1b53fe55914d3c38f17f8f542273012d19cc9509bb423f37b7c13c577a56339ad7f45273b479b1d0df837cb6e20a550c27cce0885"}}}},"signatures":[{"keyid":"97b9f13f07972ce34e386ca1fc74fa1f293ca9b1b23c23b1da178a31e8b77d0b","sig":"304402206393d229300c00882ee9e0d20a4364b554a76f8fc744cf1a5d042867946b2e05022029c8b3c4288cbdc585bb900e16236e95307050f611ea8e9261c4980aa8830ec0"}]}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Setup test data

```shell
tuf init
tuf gen-key --expires=90 --scheme="ecdsa-sha2-nistp256" root
tuf gen-key --expires=90 --scheme="ecdsa-sha2-nistp256" targets
tuf gen-key --expires=90 --scheme="ecdsa-sha2-nistp256" snapshot
tuf gen-key --expires=90 --scheme="ecdsa-sha2-nistp256" timestamp
mkdir -p staged/targets/subdir
echo "test file" > staged/targets/subdir/test.txt
tuf add "subdir/test.txt"
tuf snapshot --expires=60
tuf timestamp --expires=30
tuf commit
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"signed":{"_type":"root","spec_version":"1.0","version":1,"expires":"2025-02-18T18:35:54Z","keys":{"32ebeea523ee901ac346018dc416e153e399a9c5a337c9197e55962bf75884db":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5RfvOGyg9WsH7ss0fLE/ugmvIFIa\nzpHIEPhk4m2WPG1UVrxgIZVJQdIqOwEx9dRGVIJJb3mKBIYv4VKMBCUgfg==\n-----END PUBLIC KEY-----\n"}},"3332a046bd204e13b3c749c87179351a5b5fbf20735b37137d9694835a846c42":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK9TCGwshxW1d+pPkHt9pMLab9AZZ\n2ovDuLHI561zAhgh+5PxPvCSZc/KVzFXK854qltuh2nhVgoAJya40p6yew==\n-----END PUBLIC KEY-----\n"}},"54461f997d405cd03a912649b306f349412dc9ef2e475a89a1f18981e1a2cf5e":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPcRd5DQoGtZIEPgzUnrIHPeMUpb0\nDG4HepKiiFavuZ43kPBMl77XEXP3Fmvj650uahsqLnhrjIljkQEra41waw==\n-----END PUBLIC KEY-----\n"}},"97b9f13f07972ce34e386ca1fc74fa1f293ca9b1b23c23b1da178a31e8b77d0b":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsoSjUEAYDjgUt4jikGNdUN9bVWSz\nTCohcyDKwCCDr1rfStHF8m8ommeFfiTyYtTGdNGtdyMv4wsqLs+CVFXXKg==\n-----END PUBLIC KEY-----\n"}},"f944fd2f09223b2d8a7f7673bb31f625ed12026fb6d2a4c251a3cfd6e43f9119":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEToq4xkfD1+vpPCyeAft/GKmNOb5J\nQzBiNnle6envv61RXZ0+Zv+6RLL/GpMYJ3GQnDwz3vQ2KTT2SNbtiHlWiA==\n-----END PUBLIC KEY-----\n"}}},"roles":{"root":{"keyids":["32ebeea523ee901ac346018dc416e153e399a9c5a337c9197e55962bf75884db","54461f997d405cd03a912649b306f349412dc9ef2e475a89a1f18981e1a2cf5e"],"threshold":1},"snapshot":{"keyids":["f944fd2f09223b2d8a7f7673bb31f625ed12026fb6d2a4c251a3cfd6e43f9119"],"threshold":1},"targets":{"keyids":["97b9f13f07972ce34e386ca1fc74fa1f293ca9b1b23c23b1da178a31e8b77d0b"],"threshold":1},"timestamp":{"keyids":["3332a046bd204e13b3c749c87179351a5b5fbf20735b37137d9694835a846c42"],"threshold":1}},"consistent_snapshot":true},"signatures":[{"keyid":"32ebeea523ee901ac346018dc416e153e399a9c5a337c9197e55962bf75884db","sig":"3045022100cd1606f8a435c67277ba5afc61d7c48a2cf5c3f9433a3547fc4a8a3228711d50022047492c1bb08cb999c8525536e2822ac46a44bd69c91217655499814012ff3f1a"},{"keyid":"54461f997d405cd03a912649b306f349412dc9ef2e475a89a1f18981e1a2cf5e","sig":"304502205a37d21f635b8616dfeb0fd65459896efc13b2de9442b9fc5a8279696c0acc0d022100996988b3f2e26bc2fe352d89162a532e81123c6be4f7bfcf72300898d845c547"}]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test file
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"signed":{"_type":"timestamp","spec_version":"1.0","version":1,"expires":"2024-12-20T18:36:58Z","meta":{"snapshot.json":{"length":544,"hashes":{"sha512":"4467bf790a07dc4220baac68918d6f1bb7f6cb2a2f2663436e5817f3800ddbdc9c18b33e0a869e66eee523f9b3745799db9c7753393378fd3387ce5d74c5c3b0"},"version":1}}},"signatures":[{"keyid":"3332a046bd204e13b3c749c87179351a5b5fbf20735b37137d9694835a846c42","sig":"30450220386af40c0096bc8c7e9a5397ccd79de0ef40b04ab63f7c1c1243a9ea247e34d50221008767dabffb2022c732e7a9874a2f48bd1073c0a6cbcf86a1d6f604130f12f1d1"}]}

0 comments on commit e887c23

Please sign in to comment.