Skip to content

Commit

Permalink
Move known roles in TUF
Browse files Browse the repository at this point in the history
Roles were a bit too tightly coupled to the root roles, change
this around a tiny bit so we can add delegations support

Signed-off-by: Appu Goundan <[email protected]>
  • Loading branch information
loosebazooka committed Oct 7, 2024
1 parent e0da6bc commit 004f18a
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,22 @@ public String getIdentifier() {

@Override
public Optional<Root> loadTrustedRoot() throws IOException {
return loadRole(Role.Name.ROOT, Root.class);
return loadRole(RootRole.ROOT, Root.class);
}

@Override
public Optional<Timestamp> loadTimestamp() throws IOException {
return loadRole(Role.Name.TIMESTAMP, Timestamp.class);
return loadRole(RootRole.TIMESTAMP, Timestamp.class);
}

@Override
public Optional<Snapshot> loadSnapshot() throws IOException {
return loadRole(Role.Name.SNAPSHOT, Snapshot.class);
return loadRole(RootRole.SNAPSHOT, Snapshot.class);
}

@Override
public Optional<Targets> loadTargets() throws IOException {
return loadRole(Role.Name.TARGETS, Targets.class);
return loadRole(RootRole.TARGETS, Targets.class);
}

@Override
Expand All @@ -103,7 +103,7 @@ public void storeMeta(SignedTufMeta<?> timestamp) throws IOException {
storeRole(timestamp);
}

<T extends SignedTufMeta<?>> Optional<T> loadRole(Role.Name roleName, Class<T> tClass)
<T extends SignedTufMeta<?>> Optional<T> loadRole(String roleName, Class<T> tClass)
throws IOException {
Path roleFile = repoBaseDir.resolve(roleName + ".json");
if (!roleFile.toFile().exists()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
import com.google.common.base.Preconditions;
import dev.sigstore.http.HttpClients;
import dev.sigstore.http.ImmutableHttpParams;
import dev.sigstore.tuf.model.Role;
import dev.sigstore.tuf.model.Root;
import dev.sigstore.tuf.model.SignedTufMeta;
import dev.sigstore.tuf.model.TufMeta;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
Expand Down Expand Up @@ -62,24 +62,23 @@ public Optional<MetaFetchResult<Root>> getRootAtVersion(int version)
}

@Override
public <T extends SignedTufMeta> Optional<MetaFetchResult<T>> getMeta(Role.Name role, Class<T> t)
throws IOException, FileExceedsMaxLengthException {
public <T extends SignedTufMeta<? extends TufMeta>> Optional<MetaFetchResult<T>> getMeta(
String role, Class<T> t) throws IOException, FileExceedsMaxLengthException {
return getMeta(getFileName(role, null), t, null);
}

@Override
public <T extends SignedTufMeta> Optional<MetaFetchResult<T>> getMeta(
Role.Name role, int version, Class<T> t, Integer maxSize)
public <T extends SignedTufMeta<? extends TufMeta>> Optional<MetaFetchResult<T>> getMeta(
String role, int version, Class<T> t, Integer maxSize)
throws IOException, FileExceedsMaxLengthException {
Preconditions.checkArgument(version > 0, "version should be positive, got: %s", version);
return getMeta(getFileName(role, version), t, maxSize);
}

private static String getFileName(Role.Name role, @Nullable Integer version) {
String normalizeRoleName = role.name().toLowerCase(Locale.ROOT);
private static String getFileName(String role, @Nullable Integer version) {
return version == null
? normalizeRoleName + ".json"
: String.format(Locale.ROOT, "%d.%s.json", version, normalizeRoleName);
? role + ".json"
: String.format(Locale.ROOT, "%d.%s.json", version, role);
}

<T extends SignedTufMeta> Optional<MetaFetchResult<T>> getMeta(
Expand Down
10 changes: 5 additions & 5 deletions sigstore-java/src/main/java/dev/sigstore/tuf/MetaFetcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
*/
package dev.sigstore.tuf;

import dev.sigstore.tuf.model.Role;
import dev.sigstore.tuf.model.Root;
import dev.sigstore.tuf.model.SignedTufMeta;
import dev.sigstore.tuf.model.TufMeta;
import java.io.IOException;
import java.util.Optional;

Expand Down Expand Up @@ -49,8 +49,8 @@ Optional<MetaFetchResult<Root>> getRootAtVersion(int version)
* @throws FileExceedsMaxLengthException if the role meta at source exceeds client specified max
* size
*/
<T extends SignedTufMeta> Optional<MetaFetchResult<T>> getMeta(Role.Name name, Class<T> roleType)
throws IOException, FileExceedsMaxLengthException;
<T extends SignedTufMeta<? extends TufMeta>> Optional<MetaFetchResult<T>> getMeta(
String name, Class<T> roleType) throws IOException, FileExceedsMaxLengthException;

/**
* Fetches the specified role meta from the source
Expand All @@ -64,8 +64,8 @@ <T extends SignedTufMeta> Optional<MetaFetchResult<T>> getMeta(Role.Name name, C
* @throws FileExceedsMaxLengthException if the role meta at source exceeds client specified max
* size
*/
<T extends SignedTufMeta> Optional<MetaFetchResult<T>> getMeta(
Role.Name name, int version, Class<T> roleType, Integer maxSize)
<T extends SignedTufMeta<? extends TufMeta>> Optional<MetaFetchResult<T>> getMeta(
String name, int version, Class<T> roleType, Integer maxSize)
throws IOException, FileExceedsMaxLengthException;

byte[] fetchResource(String filename, int maxLength)
Expand Down
21 changes: 10 additions & 11 deletions sigstore-java/src/main/java/dev/sigstore/tuf/Updater.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,11 @@ Root updateRoot()
throwIfExpired(expires);
// 5.3.11) If the timestamp and / or snapshot keys have been rotated, then delete the trusted
// timestamp and snapshot metadata files.
if (hasNewKeys(preUpdateSnapshotRole, trustedRoot.getSignedMeta().getRole(Role.Name.SNAPSHOT))
if (hasNewKeys(
preUpdateSnapshotRole, trustedRoot.getSignedMeta().getRoles().get(RootRole.SNAPSHOT))
|| hasNewKeys(
preUpdateTimestampRole, trustedRoot.getSignedMeta().getRole(Role.Name.TIMESTAMP))) {
preUpdateTimestampRole,
trustedRoot.getSignedMeta().getRoles().get(RootRole.TIMESTAMP))) {
localStore.clearMetaDueToKeyRotation();
}
return trustedRoot;
Expand All @@ -174,16 +176,13 @@ private boolean hasNewKeys(RootRole oldRole, RootRole newRole) {
return !newRole.getKeyids().stream().allMatch(key -> oldRole.getKeyids().contains(key));
}

void verifyDelegate(Root trustedRoot, SignedTufMeta delegate)
void verifyDelegate(Root trustedRoot, SignedTufMeta<? extends TufMeta> delegate)
throws SignatureVerificationException, IOException, NoSuchAlgorithmException,
InvalidKeySpecException, InvalidKeyException {
InvalidKeySpecException {
verifyDelegate(
delegate.getSignatures(),
trustedRoot.getSignedMeta().getKeys(),
trustedRoot
.getSignedMeta()
.getRole(
Role.Name.valueOf(delegate.getSignedMeta().getType().toUpperCase(Locale.ROOT))),
trustedRoot.getSignedMeta().getRoles().get(delegate.getSignedMeta().getType()),
delegate.getCanonicalSignedBytes());
}

Expand Down Expand Up @@ -269,7 +268,7 @@ Optional<Timestamp> updateTimestamp(Root root)
// 1) download the timestamp.json bytes.
var timestamp =
fetcher
.getMeta(Role.Name.TIMESTAMP, Timestamp.class)
.getMeta(RootRole.TIMESTAMP, Timestamp.class)
.orElseThrow(() -> new FileNotFoundException("timestamp.json", fetcher.getSource()))
.getMetaResource();

Expand Down Expand Up @@ -305,7 +304,7 @@ Snapshot updateSnapshot(Root root, Timestamp timestamp)
int timestampSnapshotVersion = timestamp.getSignedMeta().getSnapshotMeta().getVersion();
var snapshotResult =
fetcher.getMeta(
Role.Name.SNAPSHOT,
RootRole.SNAPSHOT,
timestampSnapshotVersion,
Snapshot.class,
timestamp.getSignedMeta().getSnapshotMeta().getLengthOrDefault());
Expand Down Expand Up @@ -395,7 +394,7 @@ Targets updateTargets(Root root, Snapshot snapshot)
SnapshotMeta.SnapshotTarget targetMeta = snapshot.getSignedMeta().getTargetMeta("targets.json");
var targetsResultMaybe =
fetcher.getMeta(
Role.Name.TARGETS,
RootRole.TARGETS,
targetMeta.getVersion(),
Targets.class,
targetMeta.getLengthOrDefault());
Expand Down
13 changes: 0 additions & 13 deletions sigstore-java/src/main/java/dev/sigstore/tuf/model/Role.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package dev.sigstore.tuf.model;

import java.util.List;
import java.util.Locale;

/**
* TUF uses roles to define the set of actions a party can perform. The concept of roles allows TUF
Expand All @@ -27,18 +26,6 @@
*/
public interface Role {

enum Name {
ROOT,
SNAPSHOT,
TIMESTAMP,
TARGETS;

@Override
public String toString() {
return super.toString().toLowerCase(Locale.ROOT);
}
}

/** A list of trusted keys for this role. */
List<String> getKeyids();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,4 @@ public interface RootMeta extends TufMeta {
* href="https://theupdateframework.io/metadata/#root-metadata-rootjson">role</a>.
*/
Map<String, RootRole> getRoles();

default RootRole getRole(Role.Name name) {
return getRoles().get(name.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,9 @@
*/
@Gson.TypeAdapters
@Value.Immutable
public interface RootRole extends Role {}
public interface RootRole extends Role {
String ROOT = "root";
String SNAPSHOT = "snapshot";
String TIMESTAMP = "timestamp";
String TARGETS = "targets";
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public interface TimestampMeta extends TufMeta {
Map<String, SnapshotMeta.SnapshotTarget> getMeta();

default SnapshotMeta.SnapshotTarget getSnapshotMeta() {
return getMeta().get(Role.Name.SNAPSHOT.toString() + ".json");
return getMeta().get(RootRole.SNAPSHOT + ".json");
}
}

0 comments on commit 004f18a

Please sign in to comment.