Skip to content

Commit

Permalink
refactor: remove notion of provenance (#155)
Browse files Browse the repository at this point in the history
  • Loading branch information
algomaster99 authored Mar 1, 2024
1 parent e107a98 commit 30753ca
Show file tree
Hide file tree
Showing 17 changed files with 101 additions and 199 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.github.algomaster99.terminator.index;

import io.github.algomaster99.terminator.commons.fingerprint.ParsingHelper;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Provenance;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassFileAttributes;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -40,20 +40,22 @@ protected static class IndexFile {
@Override
public Integer call() throws Exception {
if (indexFile.input != null) {
Map<String, Set<Provenance>> currentReferenceProvenance =
Map<String, Set<ClassFileAttributes>> currentReferenceProvenance =
ParsingHelper.deserializeFingerprints(indexFile.input.toPath());
Map<String, Set<Provenance>> updatedReferenceProvenance =
Map<String, Set<ClassFileAttributes>> updatedReferenceProvenance =
createOrMergeProvenances(currentReferenceProvenance);
ParsingHelper.serialiseFingerprints(updatedReferenceProvenance, indexFile.input.toPath());
return 0;
}
if (indexFile.output != null) {
Map<String, Set<Provenance>> updatedReferenceProvenance = createOrMergeProvenances(new HashMap<>());
Map<String, Set<ClassFileAttributes>> updatedReferenceProvenance =
createOrMergeProvenances(new HashMap<>());
ParsingHelper.serialiseFingerprints(updatedReferenceProvenance, indexFile.output.toPath());
return 0;
}
throw new IllegalArgumentException("Either --input or --output must be specified");
}

abstract Map<String, Set<Provenance>> createOrMergeProvenances(Map<String, Set<Provenance>> referenceProvenance);
abstract Map<String, Set<ClassFileAttributes>> createOrMergeProvenances(
Map<String, Set<ClassFileAttributes>> referenceProvenance);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassFileAttributes;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassfileVersion;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.HashComputer;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Jdk;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Provenance;
import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
Expand All @@ -25,7 +23,8 @@ public class JdkIndexer extends BaseIndexer implements Callable<Integer> {

private static final Logger LOGGER = LoggerFactory.getLogger(JdkIndexer.class);

Map<String, Set<Provenance>> createOrMergeProvenances(Map<String, Set<Provenance>> referenceProvenance) {
Map<String, Set<ClassFileAttributes>> createOrMergeProvenances(
Map<String, Set<ClassFileAttributes>> referenceProvenance) {
List<JdkClass> jdkClasses = io.github.algomaster99.terminator.commons.fingerprint.JdkIndexer.listJdkClasses();
jdkClasses.forEach(resource -> {
try {
Expand All @@ -34,10 +33,9 @@ Map<String, Set<Provenance>> createOrMergeProvenances(Map<String, Set<Provenance
String hash = HashComputer.computeHash(classfileBytes, algorithm);
referenceProvenance.computeIfAbsent(
resource.name(),
k -> new HashSet<>(
Set.of((new Jdk(new ClassFileAttributes(classfileVersion, hash, algorithm))))));
k -> new HashSet<>(Set.of(new ClassFileAttributes(classfileVersion, hash, algorithm))));
referenceProvenance.computeIfPresent(resource.name(), (k, v) -> {
v.add(new Jdk(new ClassFileAttributes(classfileVersion, hash, algorithm)));
v.add(new ClassFileAttributes(classfileVersion, hash, algorithm));
return v;
});
} catch (NoSuchAlgorithmException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.github.algomaster99.terminator.index;

import io.github.algomaster99.terminator.commons.fingerprint.ParsingHelper;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Provenance;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassFileAttributes;
import io.github.algomaster99.terminator.commons.maven.MavenModule;
import io.github.algomaster99.terminator.commons.options.RuntimeClassInterceptorOptions;
import io.github.algomaster99.terminator.preprocess.PomTransformer;
Expand All @@ -13,6 +13,7 @@
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -48,11 +49,6 @@ public class RuntimeIndexer extends BaseIndexer implements Callable<Integer> {
required = true)
private String executableJarModule;

@Override
Map<String, Set<Provenance>> createOrMergeProvenances(Map<String, Set<Provenance>> referenceProvenance) {
return null;
}

@Override
public Integer call() throws Exception {
Path pathToTempProject = createCopyOfProject(project);
Expand Down Expand Up @@ -95,18 +91,60 @@ public Integer call() throws Exception {
Invoker invoker = new DefaultInvoker();
invoker.execute(request);

final Map<String, Set<ClassFileAttributes>> referenceProvenance = new HashMap<>();

for (Path index : candidateIndexForMerge) {
if (indexFile.input != null) {
Map<String, Set<Provenance>> currentReferenceProvenance =
ParsingHelper.deserializeFingerprints(indexFile.input.toPath());
Map<String, Set<Provenance>> updatedReferenceProvenance = ParsingHelper.deserializeFingerprints(index);
updatedReferenceProvenance.putAll(currentReferenceProvenance);
ParsingHelper.serialiseFingerprints(updatedReferenceProvenance, indexFile.input.toPath());
}
Map<String, Set<ClassFileAttributes>> generatedReferenceProvenance =
ParsingHelper.deserializeFingerprints(index);
Map<String, Set<ClassFileAttributes>> updatedReferenceProvenance =
createOrMergeProvenances(generatedReferenceProvenance);
referenceProvenance.putAll(updatedReferenceProvenance);
}

if (indexFile.input != null) {
ParsingHelper.serialiseFingerprints(referenceProvenance, indexFile.input.toPath());
} else if (indexFile.output != null) {
ParsingHelper.serialiseFingerprints(referenceProvenance, indexFile.output.toPath());
}

return 0;
}

@Override
Map<String, Set<ClassFileAttributes>> createOrMergeProvenances(
Map<String, Set<ClassFileAttributes>> referenceProvenance) {
if (indexFile.input != null) {
Map<String, Set<ClassFileAttributes>> currentReferenceProvenance =
ParsingHelper.deserializeFingerprints(indexFile.input.toPath());

referenceProvenance.forEach((k, v) -> {
if (currentReferenceProvenance.containsKey(k)) {
currentReferenceProvenance.get(k).addAll(v);
} else {
currentReferenceProvenance.put(k, v);
}
});
return currentReferenceProvenance;
}
if (indexFile.output != null) {
Map<String, Set<ClassFileAttributes>> currentReferenceProvenance;
if (indexFile.output.toPath().toFile().exists()) {
currentReferenceProvenance = ParsingHelper.deserializeFingerprints(indexFile.output.toPath());
} else {
currentReferenceProvenance = new HashMap<>();
}
referenceProvenance.forEach((k, v) -> {
if (currentReferenceProvenance.containsKey(k)) {
currentReferenceProvenance.get(k).addAll(v);
} else {
currentReferenceProvenance.put(k, v);
}
});
return currentReferenceProvenance;
}
throw new IllegalArgumentException("Either --input or --output must be specified");
}

private static Path createCopyOfProject(Path project) {
try {
Path tempDirectory = Files.createTempDirectory(project.getFileName().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
import io.github.algomaster99.terminator.commons.cyclonedx.Component__1;
import io.github.algomaster99.terminator.commons.cyclonedx.CycloneDX;
import io.github.algomaster99.terminator.commons.cyclonedx.Metadata__1;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Jdk;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Provenance;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassFileAttributes;
import io.github.algomaster99.terminator.commons.jar.JarDownloader;
import java.io.File;
import java.io.IOException;
Expand All @@ -25,7 +24,7 @@
mixinStandardHelpOptions = true,
description = "Create an index of the classfiles from SBOM")
public class SupplyChainIndexer extends BaseIndexer implements Callable<Integer> {
private static final Logger LOGGER = LoggerFactory.getLogger(Jdk.class);
private static final Logger LOGGER = LoggerFactory.getLogger(SupplyChainIndexer.class);

@CommandLine.Option(
names = {"-s", "--sbom"},
Expand All @@ -34,7 +33,8 @@ public class SupplyChainIndexer extends BaseIndexer implements Callable<Integer>
private Path sbomPath;

@Override
Map<String, Set<Provenance>> createOrMergeProvenances(Map<String, Set<Provenance>> referenceProvenance) {
Map<String, Set<ClassFileAttributes>> createOrMergeProvenances(
Map<String, Set<ClassFileAttributes>> referenceProvenance) {
Bom15Schema sbom;
try {
sbom = CycloneDX.getPojo_1_5(Files.readString(sbomPath));
Expand All @@ -51,7 +51,7 @@ Map<String, Set<Provenance>> createOrMergeProvenances(Map<String, Set<Provenance
return referenceProvenance;
}

private void processRootComponent(Bom15Schema sbom, Map<String, Set<Provenance>> referenceProvenance) {
private void processRootComponent(Bom15Schema sbom, Map<String, Set<ClassFileAttributes>> referenceProvenance) {
Metadata__1 metadata = sbom.getMetadata();
if (metadata == null) {
LOGGER.warn("Metadata is not present.");
Expand All @@ -78,7 +78,7 @@ private void processRootComponent(Bom15Schema sbom, Map<String, Set<Provenance>>
rootComponent.getVersion());
}

private void processAllComponents(Bom15Schema sbom, Map<String, Set<Provenance>> referenceProvenance) {
private void processAllComponents(Bom15Schema sbom, Map<String, Set<ClassFileAttributes>> referenceProvenance) {
for (Component__1 component : sbom.getComponents()) {
try {
File jarFile =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import static org.assertj.core.api.Assertions.assertThat;

import io.github.algomaster99.terminator.commons.fingerprint.ParsingHelper;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Provenance;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassFileAttributes;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -41,9 +41,8 @@ void useMD5asAlgorithm(@TempDir Path tempDir) {
Index.main(args);

// assert
Map<String, Set<Provenance>> referenceProvenance = ParsingHelper.deserializeFingerprints(indexFile);
referenceProvenance.forEach((key, value) -> assertThat(
value.stream().findAny().get().classFileAttributes().algorithm())
.isEqualTo("MD5"));
Map<String, Set<ClassFileAttributes>> referenceProvenance = ParsingHelper.deserializeFingerprints(indexFile);
referenceProvenance.forEach((key, value) ->
assertThat(value.stream().findAny().get().algorithm()).isEqualTo("MD5"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import static org.assertj.core.api.Assertions.assertThat;

import io.github.algomaster99.terminator.commons.fingerprint.ParsingHelper;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Provenance;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassFileAttributes;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -43,10 +43,9 @@ void useMD5asAlgorithm(@TempDir Path tempDir) {
Index.main(args);

// assert
Map<String, Set<Provenance>> referenceProvenance = ParsingHelper.deserializeFingerprints(indexFile);
Map<String, Set<ClassFileAttributes>> referenceProvenance = ParsingHelper.deserializeFingerprints(indexFile);
assertThat(referenceProvenance.keySet().size()).isEqualTo(20826);
referenceProvenance.forEach((key, value) -> assertThat(
value.stream().findAny().get().classFileAttributes().algorithm())
.isEqualTo("MD5"));
referenceProvenance.forEach((key, value) ->
assertThat(value.stream().findAny().get().algorithm()).isEqualTo("MD5"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassFileAttributes;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassfileVersion;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.HashComputer;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Provenance;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.RuntimeClass;
import io.github.algomaster99.terminator.commons.options.RuntimeClassInterceptorOptions;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
Expand All @@ -20,7 +18,7 @@

public class RuntimeClassInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(RuntimeClassInterceptor.class);
private static final Map<String, Set<Provenance>> exhaustiveListOfClasses = new ConcurrentHashMap<>();
private static final Map<String, Set<ClassFileAttributes>> exhaustiveListOfClasses = new ConcurrentHashMap<>();

public static void premain(String agentArgs, Instrumentation inst) {
RuntimeClassInterceptorOptions options = new RuntimeClassInterceptorOptions(agentArgs);
Expand All @@ -45,15 +43,14 @@ public byte[] transform(

private static byte[] recordClass(String className, byte[] classfileBuffer) {
try {
Set<Provenance> candidates = exhaustiveListOfClasses.get(className);
Set<ClassFileAttributes> candidates = exhaustiveListOfClasses.get(className);
String classFileVersion = ClassfileVersion.getVersion(classfileBuffer);
String hash = HashComputer.computeHash(classfileBuffer, "SHA-256");
if (candidates == null) {
exhaustiveListOfClasses.put(
className,
Set.of(new RuntimeClass(new ClassFileAttributes(classFileVersion, hash, "SHA-256"), true)));
className, Set.of(new ClassFileAttributes(classFileVersion, hash, "SHA-256")));
} else {
candidates.add(new RuntimeClass(new ClassFileAttributes(classFileVersion, hash, "SHA-256"), true));
candidates.add(new ClassFileAttributes(classFileVersion, hash, "SHA-256"));
}
} catch (NoSuchAlgorithmException e) {
LOGGER.error("No such algorithm: " + e.getMessage());
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SequenceWriter;
import io.github.algomaster99.terminator.commons.fingerprint.provenance.Provenance;
import io.github.algomaster99.terminator.commons.fingerprint.classfile.ClassFileAttributes;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
Expand All @@ -14,7 +14,7 @@
public class ParsingHelper {
private ParsingHelper() {}

public static void serialiseFingerprints(Map<String, Set<Provenance>> fingerprints, Path fingerprintFile) {
public static void serialiseFingerprints(Map<String, Set<ClassFileAttributes>> fingerprints, Path fingerprintFile) {
ObjectMapper mapper = new ObjectMapper();
try (SequenceWriter seq =
mapper.writer().withRootValueSeparator(System.lineSeparator()).writeValues(fingerprintFile.toFile())) {
Expand All @@ -26,14 +26,14 @@ public static void serialiseFingerprints(Map<String, Set<Provenance>> fingerprin
}
}

public static Map<String, Set<Provenance>> deserializeFingerprints(Path fingerprintFile) {
Map<String, Set<Provenance>> result = new HashMap<>();
public static Map<String, Set<ClassFileAttributes>> deserializeFingerprints(Path fingerprintFile) {
Map<String, Set<ClassFileAttributes>> result = new HashMap<>();
final ObjectMapper mapper = new ObjectMapper();
try (MappingIterator<Map<String, Set<Provenance>>> it = mapper.readerFor(
new TypeReference<Map<String, Set<Provenance>>>() {})
try (MappingIterator<Map<String, Set<ClassFileAttributes>>> it = mapper.readerFor(
new TypeReference<Map<String, Set<ClassFileAttributes>>>() {})
.readValues(fingerprintFile.toFile())) {
while (it.hasNext()) {
Map<String, Set<Provenance>> item = it.nextValue();
Map<String, Set<ClassFileAttributes>> item = it.nextValue();
result.putAll(item);
}
} catch (IOException e) {
Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit 30753ca

Please sign in to comment.