From fe49ee867c9063cf469b4dc33af0cd993194188d Mon Sep 17 00:00:00 2001 From: Appu Goundan Date: Mon, 18 Nov 2024 14:20:35 -0500 Subject: [PATCH] Handle targets with path elements filesystem store stores them down as urlencoded, this mirrors behavior of the go-tuf client Signed-off-by: Appu Goundan --- .../dev/sigstore/tuf/FileSystemTufStore.java | 8 ++++++-- .../java/dev/sigstore/tuf/TargetReader.java | 3 ++- .../java/dev/sigstore/tuf/TargetStore.java | 3 ++- .../main/java/dev/sigstore/tuf/Updater.java | 18 ++++++++++++++++-- tuf-cli/tuf-cli.xfails | 1 - 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/sigstore-java/src/main/java/dev/sigstore/tuf/FileSystemTufStore.java b/sigstore-java/src/main/java/dev/sigstore/tuf/FileSystemTufStore.java index ef829312..13b4ca5a 100644 --- a/sigstore-java/src/main/java/dev/sigstore/tuf/FileSystemTufStore.java +++ b/sigstore-java/src/main/java/dev/sigstore/tuf/FileSystemTufStore.java @@ -21,6 +21,8 @@ import dev.sigstore.tuf.model.*; import java.io.BufferedWriter; import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Optional; @@ -65,12 +67,14 @@ public String getIdentifier() { @Override public void writeTarget(String targetName, byte[] targetContents) throws IOException { - Files.write(targetsCache.resolve(targetName), targetContents); + var encoded = URLEncoder.encode(targetName, StandardCharsets.UTF_8); + Files.write(targetsCache.resolve(encoded), targetContents); } @Override public byte[] readTarget(String targetName) throws IOException { - return Files.readAllBytes(targetsCache.resolve(targetName)); + var encoded = URLEncoder.encode(targetName, StandardCharsets.UTF_8); + return Files.readAllBytes(targetsCache.resolve(encoded)); } @Override diff --git a/sigstore-java/src/main/java/dev/sigstore/tuf/TargetReader.java b/sigstore-java/src/main/java/dev/sigstore/tuf/TargetReader.java index 0a06ca8f..55e4eb22 100644 --- a/sigstore-java/src/main/java/dev/sigstore/tuf/TargetReader.java +++ b/sigstore-java/src/main/java/dev/sigstore/tuf/TargetReader.java @@ -21,7 +21,8 @@ public interface TargetReader { /** - * Reads a TUF target file from the local TUF store + * Reads a TUF target file from the local TUF store. Target names may include path elements and + * the storage engine should be consistent when handling writing and reading these. * * @param targetName the name of the target file to read (e.g. ctfe.pub) * @return the content of the file as bytes diff --git a/sigstore-java/src/main/java/dev/sigstore/tuf/TargetStore.java b/sigstore-java/src/main/java/dev/sigstore/tuf/TargetStore.java index 2a2bd25b..7ea0a1c2 100644 --- a/sigstore-java/src/main/java/dev/sigstore/tuf/TargetStore.java +++ b/sigstore-java/src/main/java/dev/sigstore/tuf/TargetStore.java @@ -28,7 +28,8 @@ public interface TargetStore extends TargetReader { String getIdentifier(); /** - * Writes a TUF target to the local target store. + * Writes a TUF target to the local target store. Target names may include path elements and the + * storage engine should be consistent when handling writing and reading these. * * @param targetName the name of the target file to write (e.g. ctfe.pub) * @param targetContents the content of the target file as bytes diff --git a/sigstore-java/src/main/java/dev/sigstore/tuf/Updater.java b/sigstore-java/src/main/java/dev/sigstore/tuf/Updater.java index fb4c3e77..d71919ff 100644 --- a/sigstore-java/src/main/java/dev/sigstore/tuf/Updater.java +++ b/sigstore-java/src/main/java/dev/sigstore/tuf/Updater.java @@ -26,6 +26,7 @@ import dev.sigstore.tuf.model.Timestamp; import dev.sigstore.tuf.model.TufMeta; import java.io.IOException; +import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; @@ -478,12 +479,25 @@ void downloadTargets(Targets targets) } void downloadTarget(String targetName, TargetData targetData) throws IOException { + var calculatedName = targetName; + var calculatedPath = ""; + // if target name includes directories then we have to process the path + if (targetName.contains("/")) { + var targetPath = Paths.get(targetName); + calculatedName = targetPath.getFileName().toString(); + calculatedPath = targetPath.getParent().toString(); + if (!calculatedPath.endsWith("/")) { + calculatedPath = calculatedPath + "/"; + } + } // 9) Download target up to length specified in bytes. verify against hash. String versionedTargetName; if (targetData.getHashes().getSha512() != null) { - versionedTargetName = targetData.getHashes().getSha512() + "." + targetName; + versionedTargetName = + calculatedPath + targetData.getHashes().getSha512() + "." + calculatedName; } else { - versionedTargetName = targetData.getHashes().getSha256() + "." + targetName; + versionedTargetName = + calculatedPath + targetData.getHashes().getSha256() + "." + calculatedName; } var targetBytes = targetFetcher.fetchResource(versionedTargetName, targetData.getLength()); diff --git a/tuf-cli/tuf-cli.xfails b/tuf-cli/tuf-cli.xfails index e22c464f..ca109077 100644 --- a/tuf-cli/tuf-cli.xfails +++ b/tuf-cli/tuf-cli.xfails @@ -1,5 +1,4 @@ test_metadata_bytes_match -test_client_downloads_expected_file_in_sub_dir test_duplicate_sig_keyids test_unusual_role_name[?] test_unusual_role_name[#]