diff --git a/.gitignore b/.gitignore index a4c3195..c9cdabe 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .idea/ .vscode/ alvarium-sdk-java.iml +sbom-tool # Compiled class file *.class diff --git a/pom.xml b/pom.xml index 6c7b1a1..2607370 100644 --- a/pom.xml +++ b/pom.xml @@ -10,14 +10,39 @@ alvarium-sdk https://alvarium.org/ - + 11 11 + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.6.0 + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + - + org.apache.httpcomponents httpclient @@ -30,7 +55,7 @@ 4.11 test - + com.google.crypto.tink tink @@ -38,47 +63,47 @@ - com.google.code.gson - gson - 2.8.8 + com.google.code.gson + gson + 2.8.8 + + + + de.huxhorn.sulky + de.huxhorn.sulky.ulid + 8.2.0 - de.huxhorn.sulky - de.huxhorn.sulky.ulid - 8.2.0 + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.5 - org.eclipse.paho - org.eclipse.paho.client.mqttv3 - 1.2.5 + io.pravega + pravega-client + 0.10.0 + + + + org.apache.logging.log4j + log4j-api + 2.21.0 + + + + org.apache.logging.log4j + log4j-core + 2.21.0 + test - io.pravega - pravega-client - 0.10.0 + org.spdx + spdx-jackson-store + 1.1.9.1 - - org.apache.logging.log4j - log4j-api - 2.21.0 - - - - org.apache.logging.log4j - log4j-core - 2.21.0 - test - - - - org.spdx - spdx-jackson-store - 1.1.9.1 - - - + \ No newline at end of file diff --git a/src/main/java/com/alvarium/DefaultSdk.java b/src/main/java/com/alvarium/DefaultSdk.java index 44dba56..709c93f 100644 --- a/src/main/java/com/alvarium/DefaultSdk.java +++ b/src/main/java/com/alvarium/DefaultSdk.java @@ -14,10 +14,6 @@ *******************************************************************************/ package com.alvarium; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - import com.alvarium.annotators.Annotator; import com.alvarium.annotators.AnnotatorConfig; import com.alvarium.annotators.AnnotatorException; @@ -25,14 +21,20 @@ import com.alvarium.contracts.Annotation; import com.alvarium.contracts.AnnotationList; import com.alvarium.contracts.AnnotationType; +import com.alvarium.hash.HashProviderFactory; +import com.alvarium.hash.HashTypeException; import com.alvarium.streams.StreamException; import com.alvarium.streams.StreamProvider; import com.alvarium.streams.StreamProviderFactory; import com.alvarium.utils.ImmutablePropertyBag; import com.alvarium.utils.PropertyBag; - import org.apache.logging.log4j.Logger; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + + public class DefaultSdk implements Sdk { private final Annotator[] annotators; private final SdkInfo config; @@ -51,20 +53,20 @@ public DefaultSdk(Annotator[] annotators, SdkInfo config, Logger logger) throws this.logger.debug("stream provider connected successfully."); } - public void create(PropertyBag properties, byte[] data) throws AnnotatorException, - StreamException { + public void create(PropertyBag properties, byte[] data) throws AnnotatorException, + StreamException, HashTypeException { final List annotations = this.createAnnotations(properties, data); this.publishAnnotations(SdkAction.CREATE, annotations); this.logger.debug("data annotated and published successfully."); } - - public void create(byte[] data) throws AnnotatorException, StreamException { - final PropertyBag properties = new ImmutablePropertyBag(new HashMap()); + + public void create(byte[] data) throws AnnotatorException, StreamException, HashTypeException { + final PropertyBag properties = new ImmutablePropertyBag(new HashMap<>()); this.create(properties, data); } - public void mutate(PropertyBag properties, byte[] oldData, byte[] newData) throws - AnnotatorException, StreamException { + public void mutate(PropertyBag properties, byte[] oldData, byte[] newData) throws + AnnotatorException, StreamException, HashTypeException { final List annotations = new ArrayList(); // source annotate the old data @@ -74,14 +76,19 @@ public void mutate(PropertyBag properties, byte[] oldData, byte[] newData) throw this.config, this.logger ); - final Annotation sourceAnnotation = sourceAnnotator.execute(properties, oldData); + + String key; + var hasher = new HashProviderFactory().getProvider(config.getHash().getType()); + key = hasher.derive(oldData); + + final Annotation sourceAnnotation = sourceAnnotator.execute(properties, oldData, key); annotations.add(sourceAnnotation); // Add annotations for new data - for (Annotation annotation: this.createAnnotations(properties, newData)) { + for (Annotation annotation : this.createAnnotations(properties, newData)) { // TLS is ignored in mutate to prevent needless penalization // See https://github.com/project-alvarium/alvarium-sdk-go/issues/19 - if(annotation.getKind() != AnnotationType.TLS) { + if (annotation.getKind() != AnnotationType.TLS) { annotations.add(annotation); } } @@ -91,32 +98,32 @@ public void mutate(PropertyBag properties, byte[] oldData, byte[] newData) throw this.logger.debug("data annotated and published successfully."); } - public void mutate(byte[] oldData, byte[] newData) throws AnnotatorException, StreamException { - final PropertyBag properties = new ImmutablePropertyBag(new HashMap()); + public void mutate(byte[] oldData, byte[] newData) throws AnnotatorException, StreamException, HashTypeException { + final PropertyBag properties = new ImmutablePropertyBag(new HashMap<>()); this.mutate(properties, oldData, newData); } public void transit(PropertyBag properties, byte[] data) throws AnnotatorException, - StreamException { + StreamException, HashTypeException { final List annotations = this.createAnnotations(properties, data); this.publishAnnotations(SdkAction.TRANSIT, annotations); this.logger.debug("data annotated and published successfully."); } - public void transit(byte[] data) throws AnnotatorException, StreamException { + public void transit(byte[] data) throws AnnotatorException, StreamException, HashTypeException { final PropertyBag properties = new ImmutablePropertyBag(new HashMap()); this.transit(properties, data); } public void publish(PropertyBag properties, byte[] data) throws AnnotatorException, - StreamException { + StreamException, HashTypeException { final List annotations = this.createAnnotations(properties, data); this.publishAnnotations(SdkAction.PUBLISH, annotations); this.logger.debug("data annotated and published successfully."); } - - public void publish(byte[] data) throws AnnotatorException, StreamException { - final PropertyBag properties = new ImmutablePropertyBag(new HashMap()); + + public void publish(byte[] data) throws AnnotatorException, StreamException, HashTypeException { + final PropertyBag properties = new ImmutablePropertyBag(new HashMap<>()); this.publish(properties, data); } @@ -127,18 +134,23 @@ public void close() throws StreamException { /** * Executes all the specified annotators and returns a list of all the created annotations + * * @param properties * @param data * @return * @throws AnnotatorException */ - private List createAnnotations(PropertyBag properties, byte[] data) - throws AnnotatorException { - final List annotations = new ArrayList(); + private List createAnnotations(PropertyBag properties, byte[] data) + throws AnnotatorException, HashTypeException { + final List annotations = new ArrayList<>(); + + String key; + var hasher = new HashProviderFactory().getProvider(config.getHash().getType()); + key = hasher.derive(data); // Annotate incoming data - for (Annotator annotator: this.annotators) { - final Annotation annotation = annotator.execute(properties, data); + for (Annotator annotator : this.annotators) { + final Annotation annotation = annotator.execute(properties, data, key); annotations.add(annotation); } @@ -146,20 +158,21 @@ private List createAnnotations(PropertyBag properties, byte[] data) } /** - * Wraps the annotation list with a publish wrapper that specifies the SDK action and the + * Wraps the annotation list with a publish wrapper that specifies the SDK action and the * content type + * * @param action * @param annotations * @throws StreamException */ - private void publishAnnotations(SdkAction action, List annotations) + private void publishAnnotations(SdkAction action, List annotations) throws StreamException { final AnnotationList annotationList = new AnnotationList(annotations); - + // publish list of annotations to the StreamProvider final PublishWrapper wrapper = new PublishWrapper( - action, - annotationList.getClass().getName(), + action, + annotationList.getClass().getName(), annotationList ); this.stream.publish(wrapper); diff --git a/src/main/java/com/alvarium/PublishWrapper.java b/src/main/java/com/alvarium/PublishWrapper.java index 9051883..b19d154 100644 --- a/src/main/java/com/alvarium/PublishWrapper.java +++ b/src/main/java/com/alvarium/PublishWrapper.java @@ -14,14 +14,9 @@ *******************************************************************************/ package com.alvarium; -import java.io.Serializable; -import java.util.Base64; +import com.alvarium.serializers.Serialization; -import com.alvarium.contracts.Annotation; -import com.alvarium.serializers.AnnotationConverter; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; +import java.io.Serializable; /** * A java bean that encapsulates the content sent through the stream providers @@ -32,6 +27,7 @@ public class PublishWrapper implements Serializable { private final String messageType; private final Object content; + public PublishWrapper(SdkAction action, String messageType, Object content) { this.action = action; this.messageType = messageType; @@ -50,33 +46,12 @@ public Object getContent() { return content; } + /** - * The content field in the returned JSON will be Base64 string encoded + * The content field in the returned JSON will be Base64 string encoded * @return String representation of the PublishWrapper JSON */ public String toJson() { - Gson gson = new GsonBuilder() - .registerTypeAdapter(Annotation.class, new AnnotationConverter()) - .disableHtmlEscaping() - .create(); - - // Change the content field to a base64 encoded string before serializing to json - final JsonElement decodedContent = gson.toJsonTree(this.content); - final String encodedContent; - - // `toString()` will work if the content is a primitive type, but will add additional - // quotes (e.g. "foo" will be "\"foo\"") but `getAsString()` will produce correct behavior but - // using `getAsString()` on a non-primitive type will throw an exception. - // This condition ensures that the correct method is called on the correct type - if (decodedContent.isJsonPrimitive()) { - encodedContent = Base64.getEncoder().encodeToString(decodedContent.getAsString().getBytes()); - } else { - encodedContent = Base64.getEncoder().encodeToString(decodedContent.toString().getBytes()); - } - - // new publish wrapper returned as JSON string with encoded content - // to prevent setting the object content value - final PublishWrapper wrapper = new PublishWrapper(action, messageType, encodedContent); - return gson.toJson(wrapper); + return Serialization.toJson(this); } } diff --git a/src/main/java/com/alvarium/Sdk.java b/src/main/java/com/alvarium/Sdk.java index 0346920..e3c5803 100644 --- a/src/main/java/com/alvarium/Sdk.java +++ b/src/main/java/com/alvarium/Sdk.java @@ -15,6 +15,7 @@ package com.alvarium; import com.alvarium.annotators.AnnotatorException; +import com.alvarium.hash.HashTypeException; import com.alvarium.streams.StreamException; import com.alvarium.utils.PropertyBag; @@ -33,8 +34,8 @@ public interface Sdk { * @throws AnnotatorException * @throws StreamException */ - public void create(PropertyBag properties, byte[] data) - throws AnnotatorException, StreamException; + public void create(PropertyBag properties, byte[] data) + throws AnnotatorException, StreamException, HashTypeException; /** * Annotates incoming data based on the list of annotators that was provided to the sdk and @@ -43,7 +44,7 @@ public void create(PropertyBag properties, byte[] data) * @throws AnnotatorException * @throws StreamException */ - public void create(byte[] data) throws AnnotatorException, StreamException; + public void create(byte[] data) throws AnnotatorException, StreamException, HashTypeException; /** * Used when the recieved piece of data is originated by a separate application. @@ -57,8 +58,8 @@ public void create(PropertyBag properties, byte[] data) * @throws AnnotatorException * @throws StreamException */ - public void transit(PropertyBag properties, byte[] data) - throws AnnotatorException, StreamException; + public void transit(PropertyBag properties, byte[] data) + throws AnnotatorException, StreamException, HashTypeException; /** * Used when the recieved piece of data is originated by a separate application. @@ -67,7 +68,7 @@ public void transit(PropertyBag properties, byte[] data) * @throws AnnotatorException * @throws StreamException */ - public void transit(byte[] data) throws AnnotatorException, StreamException; + public void transit(byte[] data) throws AnnotatorException, StreamException, HashTypeException; /** * Handles annotations related to any type of data modification. * @param properties : A property bag that may be used by specific (or custom) annotators to pass @@ -80,14 +81,14 @@ public void transit(PropertyBag properties, byte[] data) * @throws AnnotatorException * @throws StreamException */ - public void mutate(PropertyBag properties, byte[] oldData, byte[] newData) throws - AnnotatorException, StreamException; + public void mutate(PropertyBag properties, byte[] oldData, byte[] newData) throws + AnnotatorException, StreamException, HashTypeException; /** * Handles annotations related to any type of data modification. * @throws StreamException */ - public void mutate(byte[] oldData, byte[] newData) throws AnnotatorException, StreamException; + public void mutate(byte[] oldData, byte[] newData) throws AnnotatorException, StreamException, HashTypeException; /** * Publish is proposed to provide extensibility for annotators that may need @@ -104,8 +105,8 @@ public void mutate(PropertyBag properties, byte[] oldData, byte[] newData) throw * @throws AnnotatorException * @throws StreamException */ - public void publish(PropertyBag properties, byte[] data) - throws AnnotatorException, StreamException; + public void publish(PropertyBag properties, byte[] data) + throws AnnotatorException, StreamException, HashTypeException; /** * Publish is proposed to provide extensibility for annotators that may need @@ -116,7 +117,7 @@ public void publish(PropertyBag properties, byte[] data) * @throws AnnotatorException * @throws StreamException */ - public void publish(byte[] data) throws AnnotatorException, StreamException; + public void publish(byte[] data) throws AnnotatorException, StreamException, HashTypeException; /** * Closes any open connections diff --git a/src/main/java/com/alvarium/annotators/Annotator.java b/src/main/java/com/alvarium/annotators/Annotator.java index 1678039..f12dc4a 100644 --- a/src/main/java/com/alvarium/annotators/Annotator.java +++ b/src/main/java/com/alvarium/annotators/Annotator.java @@ -27,5 +27,5 @@ public interface Annotator { * @return Annotation object * @throws AnnotatorException */ - public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorException; + public Annotation execute(PropertyBag ctx, byte[] data, String key) throws AnnotatorException; } diff --git a/src/main/java/com/alvarium/annotators/ChecksumAnnotator.java b/src/main/java/com/alvarium/annotators/ChecksumAnnotator.java index bbea2f6..6c41a3c 100644 --- a/src/main/java/com/alvarium/annotators/ChecksumAnnotator.java +++ b/src/main/java/com/alvarium/annotators/ChecksumAnnotator.java @@ -20,9 +20,8 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.time.Instant; +import java.time.ZonedDateTime; -import org.apache.logging.log4j.Logger; import com.alvarium.contracts.Annotation; import com.alvarium.contracts.AnnotationType; @@ -33,135 +32,138 @@ import com.alvarium.hash.HashTypeException; import com.alvarium.sign.SignatureInfo; import com.alvarium.utils.PropertyBag; +import org.apache.logging.log4j.Logger; -public class ChecksumAnnotator extends AbstractAnnotator implements Annotator { - - final private HashType hash; - final private SignatureInfo signature; - private final AnnotationType kind; - private final LayerType layer; - private HashProvider hashProvider; +public class ChecksumAnnotator extends AbstractAnnotator implements Annotator { - protected ChecksumAnnotator(HashType hash, SignatureInfo signature, Logger logger, LayerType layer) { - super(logger); - this.hash = hash; - this.signature = signature; - this.kind = AnnotationType.CHECKSUM; - this.layer = layer; + final private HashType hash; + final private SignatureInfo signature; + private final AnnotationType kind; + private final LayerType layer; + + private HashProvider hashProvider; + + protected ChecksumAnnotator(HashType hash, SignatureInfo signature, Logger logger, LayerType layer) { + super(logger); + this.hash = hash; + this.signature = signature; + this.kind = AnnotationType.CHECKSUM; + this.layer = layer; + } + + @Override + public Annotation execute(PropertyBag ctx, byte[] data, String key) throws AnnotatorException { + + this.initHashProvider(this.hash); + final ChecksumAnnotatorProps props = ctx.getProperty( + AnnotationType.CHECKSUM.name(), + ChecksumAnnotatorProps.class + ); + + String host = ""; + boolean isSatisfied; + try { + host = InetAddress.getLocalHost().getHostName(); + // Get artifact checksum + final String checksum = this.readFile(props.getChecksumPath()); + + // Validate artifact checksum + final String artifactHash = this.hashFile(props.getArtifactPath()); + + isSatisfied = checksum.equals(artifactHash); + } catch (UnknownHostException | AnnotatorException e) { + isSatisfied = false; + //log the error using the logger + this.logger.error("Error during ChecksumAnnotator execution: ", e); } - - @Override - public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorException { - - this.initHashProvider(this.hash); - final String key = this.hashProvider.derive(data); - - final ChecksumAnnotatorProps props = ctx.getProperty( - AnnotationType.CHECKSUM.name(), - ChecksumAnnotatorProps.class - ); - - String host = ""; - boolean isSatisfied; - try{ - host = InetAddress.getLocalHost().getHostName(); - // Get artifact checksum - final String checksum = this.readFile(props.getChecksumPath()); - - // Validate artifact checksum - final String artifactHash = this.hashFile(props.getArtifactPath()); - - isSatisfied = checksum.equals(artifactHash); - } catch (UnknownHostException | AnnotatorException e) { - isSatisfied = false; - //log the error using the logger - this.logger.error("Error during ChecksumAnnotator execution: ",e); - } - final Annotation annotation = new Annotation( - key, - this.hash, - host, - layer, - this.kind, - null, - isSatisfied, - Instant.now() - ); - - final String annotationSignature = super.signAnnotation( - this.signature.getPrivateKey(), - annotation - ); - annotation.setSignature(annotationSignature); - return annotation; + final Annotation annotation = new Annotation( + key, + this.hash, + host, + layer, + this.kind, + null, + isSatisfied, + ZonedDateTime.now() + ); + + final String annotationSignature = super.signAnnotation( + this.signature.getPrivateKey(), + annotation + ); + annotation.setSignature(annotationSignature); + return annotation; + } + + /** + * Initializes a hash provider + * + * @return HashProvider + * @throws AnnotatorException - If hashing algorithm not found, + * or if an unknown exception was thrown + */ + private final void initHashProvider(HashType hashType) throws AnnotatorException { + try { + this.hashProvider = new HashProviderFactory().getProvider(hashType); + } catch (HashTypeException e) { + throw new AnnotatorException("Hashing algorithm not found, could not hash data or validate checksum", e); + } catch (Exception e) { + throw new AnnotatorException("Could not hash data or validate checksum", e); } - - /** - * Initializes a hash provider - * @return HashProvider - * @throws AnnotatorException - If hashing algorithm not found, - * or if an unknown exception was thrown - */ - private final void initHashProvider(HashType hashType) throws AnnotatorException { - try { - this.hashProvider = new HashProviderFactory().getProvider(hashType); - } catch (HashTypeException e) { - throw new AnnotatorException("Hashing algorithm not found, could not hash data or validate checksum", e); - } catch (Exception e) { - throw new AnnotatorException("Could not hash data or validate checksum", e); - } + } + + /** + * Reads a file on the local file system + * + * @param filePath + * @return String content of file + * @throws AnnotatorException - When bad file path or corrupted file given + */ + private final String readFile(String filePath) throws AnnotatorException { + final String content; + try { + content = Files.readString( + Paths.get(filePath), + StandardCharsets.UTF_8 + ); + } catch (IOException e) { + throw new AnnotatorException("Failed to read file, could not validate checksum", e); } - - /** - * Reads a file on the local file system - * @param filePath - * @return String content of file - * @throws AnnotatorException - When bad file path or corrupted file given - */ - private final String readFile(String filePath) throws AnnotatorException { - final String content; - try { - content = Files.readString( - Paths.get(filePath), - StandardCharsets.UTF_8 - ); - } catch (IOException e) { - throw new AnnotatorException("Failed to read file, could not validate checksum", e); + return content; + } + + /** + * Reads and hashes a file on the local file system in in chunks of 8KB + * + * @param filePath + * @return hash of the file's contents in string format + * @throws AnnotatorException - When bad file path or corrupted file given + */ + private final String hashFile(String filePath) throws AnnotatorException { + try { + FileInputStream fs = new FileInputStream(filePath); + final byte[] buffer = new byte[8192]; + + int bytesRead = 0; + while (true) { + bytesRead = fs.read(buffer); + if (bytesRead == -1) { // indicates EOF + break; + } else { + this.hashProvider.update(buffer, 0, bytesRead); } - return content; + } + + fs.close(); + } catch (IOException e) { + throw new AnnotatorException( + "Failed to hash artifact, could not validate checksum", + e + ); } - /** - * Reads and hashes a file on the local file system in in chunks of 8KB - * @param filePath - * @return hash of the file's contents in string format - * @throws AnnotatorException - When bad file path or corrupted file given - */ - private final String hashFile(String filePath) throws AnnotatorException { - try { - FileInputStream fs = new FileInputStream(filePath); - final byte[] buffer = new byte[8192]; - - int bytesRead = 0; - while (true) { - bytesRead = fs.read(buffer); - if (bytesRead == -1) { // indicates EOF - break; - } else { - this.hashProvider.update(buffer, 0, bytesRead); - } - } - - fs.close(); - } catch(IOException e) { - throw new AnnotatorException( - "Failed to hash artifact, could not validate checksum", - e - ); - } - - return this.hashProvider.getValue(); - } + return this.hashProvider.getValue(); + } } diff --git a/src/main/java/com/alvarium/annotators/MockAnnotator.java b/src/main/java/com/alvarium/annotators/MockAnnotator.java index 2ce39fe..3e74a07 100644 --- a/src/main/java/com/alvarium/annotators/MockAnnotator.java +++ b/src/main/java/com/alvarium/annotators/MockAnnotator.java @@ -16,14 +16,12 @@ import java.net.InetAddress; import java.net.UnknownHostException; -import java.time.Instant; +import java.time.ZonedDateTime; import com.alvarium.contracts.Annotation; import com.alvarium.contracts.AnnotationType; import com.alvarium.contracts.LayerType; -import com.alvarium.hash.HashProviderFactory; import com.alvarium.hash.HashType; -import com.alvarium.hash.HashTypeException; import com.alvarium.sign.SignatureInfo; import com.alvarium.utils.PropertyBag; @@ -45,19 +43,15 @@ protected MockAnnotator(MockAnnotatorConfig cfg, HashType hash, SignatureInfo si this.layer = layer; } - public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorException { - final HashProviderFactory hashFactory = new HashProviderFactory(); + public Annotation execute(PropertyBag ctx, byte[] data, String key) throws AnnotatorException { try { - final String key = hashFactory.getProvider(hash).derive(data); final String host = InetAddress.getLocalHost().getHostName(); final String sig = signature.getPublicKey().getType().toString(); - final Annotation annotation = new Annotation(key, hash, host, layer, kind, sig, cfg.getShouldSatisfy(), Instant.now()); + final Annotation annotation = new Annotation(key, hash, host, layer, kind, sig, cfg.getShouldSatisfy(), ZonedDateTime.now()); return annotation; - } catch (HashTypeException e) { - throw new AnnotatorException("failed to hash data", e); } catch (UnknownHostException e) { throw new AnnotatorException("Could not get hostname", e); } - } + } } diff --git a/src/main/java/com/alvarium/annotators/PkiAnnotator.java b/src/main/java/com/alvarium/annotators/PkiAnnotator.java index 9c4d9af..fb88ef4 100644 --- a/src/main/java/com/alvarium/annotators/PkiAnnotator.java +++ b/src/main/java/com/alvarium/annotators/PkiAnnotator.java @@ -14,18 +14,17 @@ *******************************************************************************/ package com.alvarium.annotators; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.time.Instant; - -import org.apache.logging.log4j.Logger; - import com.alvarium.contracts.Annotation; import com.alvarium.contracts.AnnotationType; import com.alvarium.contracts.LayerType; import com.alvarium.hash.HashType; import com.alvarium.sign.SignatureInfo; import com.alvarium.utils.PropertyBag; +import org.apache.logging.log4j.Logger; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.time.ZonedDateTime; class PkiAnnotator extends AbstractPkiAnnotator implements Annotator { private final HashType hash; @@ -41,9 +40,7 @@ protected PkiAnnotator(HashType hash, SignatureInfo signature, Logger logger, La this.layer = layer; } - public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorException { - final String key = super.deriveHash(hash, data); - + public Annotation execute(PropertyBag ctx, byte[] data, String key) throws AnnotatorException { final Signable signable = Signable.fromJson(new String(data)); String host = ""; @@ -65,7 +62,7 @@ public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorExceptio kind, null, isSatisfied, - Instant.now()); + ZonedDateTime.now()); final String annotationSignature = super.signAnnotation(signature.getPrivateKey(), annotation); annotation.setSignature(annotationSignature); diff --git a/src/main/java/com/alvarium/annotators/PkiHttpAnnotator.java b/src/main/java/com/alvarium/annotators/PkiHttpAnnotator.java index f91ca75..d200ded 100644 --- a/src/main/java/com/alvarium/annotators/PkiHttpAnnotator.java +++ b/src/main/java/com/alvarium/annotators/PkiHttpAnnotator.java @@ -19,8 +19,8 @@ import java.net.URISyntaxException; import java.net.UnknownHostException; import java.nio.file.Paths; -import java.time.Instant; import java.nio.file.Path; +import java.time.ZonedDateTime; import com.alvarium.annotators.http.ParseResult; import com.alvarium.annotators.http.ParseResultException; @@ -50,16 +50,14 @@ protected PkiHttpAnnotator(HashType hash, SignatureInfo signature, Logger logger this.layer = layer; } - public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorException { - final String key = super.deriveHash(hash, data); - + public Annotation execute(PropertyBag ctx, byte[] data, String key) throws AnnotatorException { HttpUriRequest request; try { request = ctx.getProperty(AnnotationType.PKIHttp.name(), HttpUriRequest.class); } catch (IllegalArgumentException e) { throw new AnnotatorException(String.format("Property %s not found", AnnotationType.PKIHttp.name())); } - ParseResult parsed; + ParseResult parsed; try { parsed = new ParseResult(request); } catch (URISyntaxException e) { @@ -86,15 +84,15 @@ public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorExceptio String host = ""; boolean isSatisfied; - try{ + try { host = InetAddress.getLocalHost().getHostName(); isSatisfied = verifySignature(sig.getPublicKey(), signable); } catch (UnknownHostException | AnnotatorException e) { isSatisfied = false; - this.logger.error("Error during PkiHttpAnnotator execution: ",e); + this.logger.error("Error during PkiHttpAnnotator execution: ", e); } - + final Annotation annotation = new Annotation( key, hash, @@ -103,7 +101,7 @@ public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorExceptio kind, null, isSatisfied, - Instant.now()); + ZonedDateTime.now()); final String annotationSignature = super.signAnnotation(sig.getPrivateKey(), annotation); annotation.setSignature(annotationSignature); diff --git a/src/main/java/com/alvarium/annotators/SbomAnnotator.java b/src/main/java/com/alvarium/annotators/SbomAnnotator.java index c5bd074..64a07d8 100644 --- a/src/main/java/com/alvarium/annotators/SbomAnnotator.java +++ b/src/main/java/com/alvarium/annotators/SbomAnnotator.java @@ -15,12 +15,12 @@ import java.net.InetAddress; import java.net.UnknownHostException; -import java.time.Instant; +import java.time.ZonedDateTime; +import com.alvarium.annotators.sbom.SbomException; import org.apache.logging.log4j.Logger; import com.alvarium.annotators.sbom.SbomAnnotatorConfig; -import com.alvarium.annotators.sbom.SbomException; import com.alvarium.annotators.sbom.SbomProvider; import com.alvarium.annotators.sbom.SbomProviderFactory; import com.alvarium.contracts.Annotation; @@ -46,18 +46,16 @@ protected SbomAnnotator(SbomAnnotatorConfig cfg, HashType hash, SignatureInfo si this.kind = AnnotationType.SBOM; this.layer = layer; } - - @Override - public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorException { - final String key = deriveHash(this.hash, data); + @Override + public Annotation execute(PropertyBag ctx, byte[] data, String key) throws AnnotatorException { String host = ""; - try{ + try { host = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { - this.logger.error("Error during SbomAnnotator execution: ",e); + this.logger.error("Error during SbomAnnotator execution: ", e); } - + boolean isSatisfied = false; try { final SbomProvider sbom = new SbomProviderFactory().getProvider(this.cfg, this.logger); @@ -71,24 +69,24 @@ public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorExceptio } catch (Exception e) { this.logger.error("Error during SbomAnnotator execution: ", e); } - + final Annotation annotation = new Annotation( - key, - hash, - host, + key, + hash, + host, layer, - kind, - null, - isSatisfied, - Instant.now() + kind, + null, + isSatisfied, + ZonedDateTime.now() ); final String annotationSignature = super.signAnnotation( - this.signature.getPrivateKey(), + this.signature.getPrivateKey(), annotation ); annotation.setSignature(annotationSignature); - return annotation; + return annotation; } } diff --git a/src/main/java/com/alvarium/annotators/SourceAnnotator.java b/src/main/java/com/alvarium/annotators/SourceAnnotator.java index 8011d73..d37ee4f 100644 --- a/src/main/java/com/alvarium/annotators/SourceAnnotator.java +++ b/src/main/java/com/alvarium/annotators/SourceAnnotator.java @@ -16,7 +16,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; -import java.time.Instant; +import java.time.ZonedDateTime; import org.apache.logging.log4j.Logger; @@ -36,19 +36,16 @@ class SourceAnnotator extends AbstractAnnotator implements Annotator { private final AnnotationType kind; private final SignatureInfo signatureInfo; private final LayerType layer; - + protected SourceAnnotator(HashType hash, SignatureInfo signatureInfo, Logger logger, LayerType layer) { super(logger); this.hash = hash; this.kind = AnnotationType.SOURCE; this.signatureInfo = signatureInfo; this.layer = layer; - } - - public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorException { - // hash incoming data - final String key = super.deriveHash(this.hash, data); + } + public Annotation execute(PropertyBag ctx, byte[] data, String key) throws AnnotatorException { // get hostname if available String host = ""; boolean isSatisfied; @@ -56,17 +53,17 @@ public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorExceptio host = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { isSatisfied = false; - this.logger.error("Error during SourceAnnotator execution: ",e); + this.logger.error("Error during SourceAnnotator execution: ", e); } isSatisfied = true; // create an annotation without signature final Annotation annotation = new Annotation(key, this.hash, host, layer, this.kind, null, isSatisfied, - Instant.now()); - + ZonedDateTime.now()); + final String signature = super.signAnnotation(signatureInfo.getPrivateKey(), annotation); annotation.setSignature(signature); return annotation; - } + } } diff --git a/src/main/java/com/alvarium/annotators/SourceCodeAnnotator.java b/src/main/java/com/alvarium/annotators/SourceCodeAnnotator.java index 00f659b..cdaab87 100644 --- a/src/main/java/com/alvarium/annotators/SourceCodeAnnotator.java +++ b/src/main/java/com/alvarium/annotators/SourceCodeAnnotator.java @@ -24,11 +24,12 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.text.Collator; -import java.time.Instant; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; + import org.apache.logging.log4j.Logger; import com.alvarium.contracts.Annotation; @@ -43,180 +44,182 @@ class SourceCodeAnnotator extends AbstractAnnotator implements Annotator { - private final HashType hash; - private final AnnotationType kind; - private final SignatureInfo signature; - private final LayerType layer; - - private HashProvider hashProvider; - - protected SourceCodeAnnotator(HashType hash, SignatureInfo signature, Logger logger, LayerType layer) { - super(logger); - this.hash = hash; - this.kind = AnnotationType.SourceCode; - this.signature = signature; - this.layer = layer; + private final HashType hash; + private final AnnotationType kind; + private final SignatureInfo signature; + private final LayerType layer; + + private HashProvider hashProvider; + + protected SourceCodeAnnotator(HashType hash, SignatureInfo signature, Logger logger, LayerType layer) { + super(logger); + this.hash = hash; + this.kind = AnnotationType.SourceCode; + this.signature = signature; + this.layer = layer; + } + + // File (git working directory) is to be passed in the ctx bag + // expects commitHash and directory from ctx + @Override + public Annotation execute(PropertyBag ctx, byte[] data, String key) throws AnnotatorException { + this.initHashProvider(this.hash); + final SourceCodeAnnotatorProps props = ctx.getProperty( + AnnotationType.SourceCode.name(), + SourceCodeAnnotatorProps.class + ); + + String host = ""; + boolean isSatisfied; + try { + host = InetAddress.getLocalHost().getHostName(); + final String checksum = this.readChecksum(props.getChecksumPath()); + final String generatedChecksum = this.generateChecksum(props.getSourceCodePath()); + isSatisfied = generatedChecksum.equals(checksum); + } catch (UnknownHostException | AnnotatorException e) { + isSatisfied = false; + this.logger.error("Error during SourceCodeAnnotator execution: ", e); } - // File (git working directory) is to be passed in the ctx bag - // expects commitHash and directory from ctx - @Override - public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorException { - this.initHashProvider(this.hash); - final String key = this.hashProvider.derive(data); - - final SourceCodeAnnotatorProps props = ctx.getProperty( - AnnotationType.SourceCode.name(), - SourceCodeAnnotatorProps.class - ); - - String host = ""; - boolean isSatisfied; - try{ - host = InetAddress.getLocalHost().getHostName(); - final String checksum = this.readChecksum(props.getChecksumPath()); - final String generatedChecksum = this.generateChecksum(props.getSourceCodePath()); - isSatisfied = generatedChecksum.equals(checksum); - } catch (UnknownHostException | AnnotatorException e) { - isSatisfied = false; - this.logger.error("Error during SourceCodeAnnotator execution: ",e); - } - - final Annotation annotation = new Annotation( - key, - hash, - host, - layer, - kind, - null, - isSatisfied, - Instant.now()); - - final String annotationSignature = super.signAnnotation(signature.getPrivateKey(), annotation); - annotation.setSignature(annotationSignature); - return annotation; + final Annotation annotation = new Annotation( + key, + hash, + host, + layer, + kind, + null, + isSatisfied, + ZonedDateTime.now()); + + final String annotationSignature = super.signAnnotation(signature.getPrivateKey(), annotation); + annotation.setSignature(annotationSignature); + return annotation; + } + + private String readChecksum(String path) throws AnnotatorException { + try { + final Path p = Paths.get(path); + return Files.readString(p); + } catch (IOException e) { + throw new AnnotatorException("Failed to read file, could not validate checksum", e); + } catch (SecurityException e) { + throw new AnnotatorException( + "Insufficient permission to access file, could not validate checksum", + e + ); + } catch (OutOfMemoryError e) { + throw new AnnotatorException( + "Failed to read file due to size larger than 2GB, could not validate checksum " + e + ); + } catch (Exception e) { + throw new AnnotatorException("Could not validate checksum"); } - - private String readChecksum(String path) throws AnnotatorException { - try { - final Path p = Paths.get(path); - return Files.readString(p); - } catch (IOException e) { - throw new AnnotatorException("Failed to read file, could not validate checksum", e); - } catch (SecurityException e) { - throw new AnnotatorException( - "Insufficient permission to access file, could not validate checksum", - e - ); - } catch (OutOfMemoryError e) { - throw new AnnotatorException( - "Failed to read file due to size larger than 2GB, could not validate checksum " + e - ); - } catch (Exception e) { - throw new AnnotatorException("Could not validate checksum"); - } + } + + /** + * Initializes the hash provider used to hash the source code + * + * @return HashProvider + * @throws AnnotatorException - If hashing algorithm not found, + * or if an unknown exception was thrown + */ + private final void initHashProvider(HashType hashType) throws AnnotatorException { + try { + this.hashProvider = new HashProviderFactory().getProvider(hashType); + } catch (HashTypeException e) { + throw new AnnotatorException("Hashing algorithm not found, could not hash data or generate checksum", e); + } catch (Exception e) { + throw new AnnotatorException("Could not hash data or generate checksum", e); } - - /** - * Initializes the hash provider used to hash the source code - * @return HashProvider - * @throws AnnotatorException - If hashing algorithm not found, - * or if an unknown exception was thrown - */ - private final void initHashProvider(HashType hashType) throws AnnotatorException { - try { - this.hashProvider = new HashProviderFactory().getProvider(hashType); - } catch (HashTypeException e) { - throw new AnnotatorException("Hashing algorithm not found, could not hash data or generate checksum", e); - } catch (Exception e) { - throw new AnnotatorException("Could not hash data or generate checksum", e); + } + + /** + * Recursively gets all files in a directory as a list of absolute paths + * + * @param path + * @return List of all files in directory + */ + private List getAllFiles(String path) { + List files = new ArrayList<>(); + File directory = new File(path); + + if (directory.isDirectory()) { + File[] directoryFiles = directory.listFiles(); + if (directoryFiles != null) { + for (File file : directoryFiles) { + if (file.isFile()) { + files.add(file.getAbsolutePath()); + } else if (file.isDirectory()) { + files.addAll(getAllFiles(file.getAbsolutePath())); + } } + } + } else if (directory.isFile()) { + files.add(directory.getAbsolutePath()); } - - /** - * Recursively gets all files in a directory as a list of absolute paths - * @param path - * @return List of all files in directory - */ - private List getAllFiles(String path) { - List files = new ArrayList<>(); - File directory = new File(path); - - if (directory.isDirectory()) { - File[] directoryFiles = directory.listFiles(); - if (directoryFiles != null) { - for (File file : directoryFiles) { - if (file.isFile()) { - files.add(file.getAbsolutePath()); - } else if (file.isDirectory()) { - files.addAll(getAllFiles(file.getAbsolutePath())); - } - } - } - } else if (directory.isFile()) { - files.add(directory.getAbsolutePath()); + return files; + } + + /** + * Reads and hashes a file on the local file system in in chunks of 8KB + * + * @param filePath + * @return hash of the file's contents in string format + * @throws AnnotatorException - When bad file path or corrupted file given + */ + private final String readAndHashFile(String filePath) throws AnnotatorException { + try { + FileInputStream fs = new FileInputStream(filePath); + final byte[] buffer = new byte[8192]; + int bytesRead = 0; + while (true) { + bytesRead = fs.read(buffer); + if (bytesRead == -1) { // indicates EOF + break; + } else { + this.hashProvider.update(buffer, 0, bytesRead); } - return files; + } + fs.close(); + } catch (OutOfMemoryError e) { + throw new AnnotatorException( + "Failed to read file due to size larger than 2GB, could not validate checksum" + e + ); + } catch (IOException e) { + throw new AnnotatorException( + "Failed to read file contents, could not generate checksum", + e + ); + } catch (SecurityException e) { + throw new AnnotatorException( + "Insufficient permission to access file, could not validate checksum", + e + ); + } catch (Exception e) { + throw new AnnotatorException("Could not validate checksum", e); } - - /** - * Reads and hashes a file on the local file system in in chunks of 8KB - * @param filePath - * @return hash of the file's contents in string format - * @throws AnnotatorException - When bad file path or corrupted file given - */ - private final String readAndHashFile(String filePath) throws AnnotatorException { - try { - FileInputStream fs = new FileInputStream(filePath); - final byte[] buffer = new byte[8192]; - int bytesRead = 0; - while (true) { - bytesRead = fs.read(buffer); - if (bytesRead == -1) { // indicates EOF - break; - } else { - this.hashProvider.update(buffer, 0, bytesRead); - } - } - fs.close(); - } catch (OutOfMemoryError e) { - throw new AnnotatorException( - "Failed to read file due to size larger than 2GB, could not validate checksum" + e - ); - } catch (IOException e) { - throw new AnnotatorException( - "Failed to read file contents, could not generate checksum", - e - ); - } catch (SecurityException e) { - throw new AnnotatorException( - "Insufficient permission to access file, could not validate checksum", - e - ); - } catch (Exception e) { - throw new AnnotatorException("Could not validate checksum", e); - } - return this.hashProvider.getValue(); + return this.hashProvider.getValue(); + } + + /** + * Computes the hash of all files hashes and their corresponding paths in the specified directory and returns the + * hash value as a string. + * + * @param path the path of the directory to hash + * @return the hash value of the directory as a string + * @throws AnnotatorException if an error occurs while hashing the directory + */ + private String generateChecksum(String path) throws AnnotatorException { + List filePaths = getAllFiles(path); + for (int i = 0; i < filePaths.size(); i++) { + String hashThenPath = readAndHashFile(filePaths.get(i)) + " " + filePaths.get(i); + filePaths.set(i, hashThenPath); } + Collections.sort(filePaths, Collator.getInstance(Locale.US)); - /** - * Computes the hash of all files hashes and their corresponding paths in the specified directory and returns the - * hash value as a string. - * @param path the path of the directory to hash - * @return the hash value of the directory as a string - * @throws AnnotatorException if an error occurs while hashing the directory - */ - private String generateChecksum(String path) throws AnnotatorException { - List filePaths = getAllFiles(path); - for(int i = 0 ; i vulnerabilities; @@ -88,7 +80,7 @@ public Annotation execute(PropertyBag ctx, byte[] data) throws AnnotatorExceptio this.kind, null, isSatisfied, - Instant.now() + ZonedDateTime.now() ); final String annotationSignature = super.signAnnotation( diff --git a/src/main/java/com/alvarium/contracts/Annotation.java b/src/main/java/com/alvarium/contracts/Annotation.java index 4991d29..b9d37f6 100644 --- a/src/main/java/com/alvarium/contracts/Annotation.java +++ b/src/main/java/com/alvarium/contracts/Annotation.java @@ -15,22 +15,20 @@ package com.alvarium.contracts; -import java.io.Serializable; -import java.time.Instant; - import com.alvarium.hash.HashType; -import com.alvarium.serializers.InstantConverter; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - +import com.alvarium.serializers.Serialization; +import com.alvarium.utils.IDGenerator; import de.huxhorn.sulky.ulid.ULID; +import java.io.Serializable; +import java.time.ZonedDateTime; + /** * A java bean that encapsulates all of the data related to a specific annotation. * this will be generated by the annotators. */ public class Annotation implements Serializable { - private final String id; + private final String id; private final String key; private final HashType hash; private final String host; @@ -38,8 +36,8 @@ public class Annotation implements Serializable { private final LayerType layer; private final AnnotationType kind; private String signature; - private final Boolean isSatisfied; - private final Instant timestamp; + private final boolean isSatisfied; + private final ZonedDateTime timestamp; // TagEnvKey is an environment key used to associate annotations with specific metadata, // aiding in the linkage of scores across different layers of the stack. For instance, in the "app" layer, // it is utilized to retrieve the commit SHA of the workload where the application is running, @@ -47,9 +45,8 @@ public class Annotation implements Serializable { public static final String TAG_ENV_KEY = "TAG"; public Annotation(String key, HashType hash, String host, LayerType layer, AnnotationType kind, String signature, - Boolean isSatisfied, Instant timestamp) { - ULID ulid = new ULID(); - this.id = ulid.nextULID(); + Boolean isSatisfied, ZonedDateTime timestamp) { + this.id = IDGenerator.generate(); this.key = key; this.hash = hash; this.host = host; @@ -58,85 +55,84 @@ public Annotation(String key, HashType hash, String host, LayerType layer, Annot this.kind = kind; this.signature = signature; this.isSatisfied = isSatisfied; - this.timestamp = timestamp; - } - - //setters - - public void setSignature(String signature) { - this.signature = signature; - } - - // getters - - public String getId() { - return this.id; - } - - public String getKey() { - return this.key; - } - - public HashType getHash() { - return this.hash; - } - - public String getHost() { - return this.host; - } + this.timestamp = timestamp; - public String getTag() { - return this.tag; - } - - public LayerType getLayer() { - return this.layer; - } - - public AnnotationType getKind() { - return this.kind; - } - - public String getSignature() { - return this.signature; - } + } - public Boolean getIsSatisfied() { - return this.isSatisfied; - } + //setters - public Instant getTimestamp() { - return this.timestamp; - } - - /** - * returns the JSON representation of the Annotation object - * @return json string representation - */ - public String toJson() { - Gson gson = new GsonBuilder().registerTypeAdapter(Instant.class, new InstantConverter()) - .create(); - return gson.toJson(this, Annotation.class); - } - - /** - * instaniates an Annotation object from a json representation - * @param json input JSON string - * @return Annotation Object - */ - public static Annotation fromJson(String json) { - Gson gson = new GsonBuilder().registerTypeAdapter(Instant.class, new InstantConverter()) - .create(); - return gson.fromJson(json, Annotation.class); - } - - private String getTagValue(LayerType layer) { - switch(layer){ - case Application: - return System.getenv(TAG_ENV_KEY) == null ? "" : System.getenv(TAG_ENV_KEY); - default: - break; - } - return ""; + public void setSignature(String signature) { + this.signature = signature; + } + + // getters + + public String getId() { + return this.id; + } + + public String getKey() { + return this.key; + } + + public HashType getHash() { + return this.hash; + } + + public String getHost() { + return this.host; + } + + public String getTag() { + return this.tag; + } + + public LayerType getLayer() { + return this.layer; + } + + public AnnotationType getKind() { + return this.kind; + } + + public String getSignature() { + return this.signature; + } + + public Boolean getIsSatisfied() { + return this.isSatisfied; + } + + public ZonedDateTime getTimestamp() { + return this.timestamp; + } + + /** + * returns the JSON representation of the Annotation object + * + * @return json string representation + */ + public String toJson() { + return Serialization.toJson(this); + } + + /** + * instaniates an Annotation object from a json representation + * + * @param json input JSON string + * @return Annotation Object + */ + public static Annotation fromJson(String json) { + return Serialization.annotationFromJson(json); + } + + private String getTagValue(LayerType layer) { + switch (layer) { + case Application: + return System.getenv(TAG_ENV_KEY) == null ? "" : System.getenv(TAG_ENV_KEY); + default: + break; } + return ""; + } } diff --git a/src/main/java/com/alvarium/contracts/AnnotationList.java b/src/main/java/com/alvarium/contracts/AnnotationList.java index 1f1618a..f9f3e2a 100644 --- a/src/main/java/com/alvarium/contracts/AnnotationList.java +++ b/src/main/java/com/alvarium/contracts/AnnotationList.java @@ -14,11 +14,9 @@ *******************************************************************************/ package com.alvarium.contracts; -import java.util.List; +import com.alvarium.serializers.Serialization; -import com.alvarium.serializers.AnnotationConverter; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; +import java.util.List; /** @@ -30,7 +28,7 @@ public class AnnotationList { public AnnotationList(Annotation[] annotations) { this.items = List.of(annotations); } - + public AnnotationList(List annotations) { this.items = annotations; } @@ -40,18 +38,10 @@ public List getAnnotations() { } public String toJson() { - Gson gson = new GsonBuilder() - .registerTypeAdapter(Annotation.class, new AnnotationConverter()) - .create(); - - return gson.toJson(this); + return Serialization.toJson(this); } public static AnnotationList fromJson(String json) { - Gson gson = new GsonBuilder() - .registerTypeAdapter(Annotation.class, new AnnotationConverter()) - .create(); - - return gson.fromJson(json, AnnotationList.class); + return Serialization.annotationListFromJson(json); } } diff --git a/src/main/java/com/alvarium/serializers/AnnotationConverter.java b/src/main/java/com/alvarium/serializers/AnnotationConverter.java index e957605..8468316 100644 --- a/src/main/java/com/alvarium/serializers/AnnotationConverter.java +++ b/src/main/java/com/alvarium/serializers/AnnotationConverter.java @@ -1,6 +1,5 @@ - /******************************************************************************* - * Copyright 2021 Dell Inc. + * Copyright 2023 Dell Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at @@ -14,24 +13,27 @@ *******************************************************************************/ package com.alvarium.serializers; -import java.lang.reflect.Type; - import com.alvarium.contracts.Annotation; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; +import com.google.gson.*; +import java.lang.reflect.Type; -public class AnnotationConverter implements JsonSerializer, JsonDeserializer { +public class AnnotationConverter implements JsonSerializer { + @Override public JsonElement serialize(Annotation src, Type typeOfSrc, JsonSerializationContext context) { - return JsonParser.parseString(src.toJson()); - } + var json = new JsonObject(); + + json.add("id", new JsonPrimitive(src.getId())); + json.add("type", new JsonPrimitive(src.getKind().name())); + json.add("tag", new JsonPrimitive(src.getTag())); + json.add("hash", new JsonPrimitive(src.getHash().name())); + json.add("host", new JsonPrimitive(src.getHost())); + json.add("layer", new JsonPrimitive(src.getLayer().name())); + json.add("signature", src.getSignature() == null ? null : new JsonPrimitive(src.getSignature())); + json.add("timestamp", context.serialize(src.getTimestamp())); + json.add("isSatisfied", new JsonPrimitive(src.getIsSatisfied())); - public Annotation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { - return Annotation.fromJson(json.toString()); + return json; } } diff --git a/src/main/java/com/alvarium/serializers/AnnotationListConverter.java b/src/main/java/com/alvarium/serializers/AnnotationListConverter.java new file mode 100644 index 0000000..ad9bdc2 --- /dev/null +++ b/src/main/java/com/alvarium/serializers/AnnotationListConverter.java @@ -0,0 +1,15 @@ +package com.alvarium.serializers; + +import com.alvarium.contracts.AnnotationList; +import com.google.gson.JsonElement; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; + +public class AnnotationListConverter implements JsonSerializer { + @Override + public JsonElement serialize(AnnotationList src, Type typeOfSrc, JsonSerializationContext context) { + return context.serialize(src.getAnnotations()); + } +} diff --git a/src/main/java/com/alvarium/serializers/InstantConverter.java b/src/main/java/com/alvarium/serializers/InstantConverter.java deleted file mode 100644 index 614210a..0000000 --- a/src/main/java/com/alvarium/serializers/InstantConverter.java +++ /dev/null @@ -1,53 +0,0 @@ - -/******************************************************************************* - * Copyright 2021 Dell Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License - * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - * or implied. See the License for the specific language governing permissions and limitations under - * the License. - *******************************************************************************/ -package com.alvarium.serializers; - -import java.lang.reflect.Type; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -/** - * A converter of Instant datatype to RFC3339 string representation and vice versa - */ -public class InstantConverter implements JsonSerializer, JsonDeserializer{ - - public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) { - // a workaround to preserve the zone information - DateTimeFormatter f = DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.systemDefault()); - ZonedDateTime zdt = ZonedDateTime.parse(DateTimeFormatter.ISO_INSTANT.format(src), f); - String raw = zdt.toString(); - - if (raw.indexOf('[') > 0) { - return new JsonPrimitive(zdt.toString().substring(0, raw.indexOf('['))); - } - return new JsonPrimitive(raw); - } - - @Override - public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - return DateTimeFormatter.ISO_ZONED_DATE_TIME.parse(json.getAsString(), Instant::from); - } -} diff --git a/src/main/java/com/alvarium/serializers/PublishWrapperConverter.java b/src/main/java/com/alvarium/serializers/PublishWrapperConverter.java new file mode 100644 index 0000000..cc44981 --- /dev/null +++ b/src/main/java/com/alvarium/serializers/PublishWrapperConverter.java @@ -0,0 +1,23 @@ +package com.alvarium.serializers; + +import com.alvarium.PublishWrapper; +import com.google.gson.*; + +import java.lang.reflect.Type; +import java.util.Base64; + +public class PublishWrapperConverter implements JsonSerializer { + + + @Override + public JsonElement serialize(PublishWrapper src, Type typeOfSrc, JsonSerializationContext context) { + var json = new JsonObject(); + json.add("action", new JsonPrimitive(src.getAction().name())); + json.add("type", new JsonPrimitive(src.getMessageType())); + + String contentJsonString = context.serialize(src.getContent()).toString(); + + json.add("content", new JsonPrimitive(Base64.getEncoder().encodeToString(contentJsonString.getBytes()))); + return json; + } +} diff --git a/src/main/java/com/alvarium/serializers/Serialization.java b/src/main/java/com/alvarium/serializers/Serialization.java new file mode 100644 index 0000000..3516735 --- /dev/null +++ b/src/main/java/com/alvarium/serializers/Serialization.java @@ -0,0 +1,43 @@ +package com.alvarium.serializers; + +import com.alvarium.PublishWrapper; +import com.alvarium.contracts.Annotation; +import com.alvarium.contracts.AnnotationList; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.time.ZonedDateTime; + +public class Serialization { + + + private static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(PublishWrapper.class, new PublishWrapperConverter()) + .registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeConverter()) + .registerTypeAdapter(Annotation.class, new AnnotationConverter()) + .registerTypeAdapter(AnnotationList.class, new AnnotationListConverter()) + .disableHtmlEscaping() + .create(); + + public static String toJson(PublishWrapper wrapper) { + return GSON.toJson(wrapper); + } + + public static String toJson(Annotation annotation) { + return GSON.toJson(annotation); + } + + public static String toJson(AnnotationList list) { + return GSON.toJson(list); + } + + + public static Annotation annotationFromJson(String jsonAnnotation) { + return GSON.fromJson(jsonAnnotation, Annotation.class); + } + + public static AnnotationList annotationListFromJson(String jsonAnnotation) { + return GSON.fromJson(jsonAnnotation, AnnotationList.class); + } + +} diff --git a/src/main/java/com/alvarium/serializers/ZonedDateTimeConverter.java b/src/main/java/com/alvarium/serializers/ZonedDateTimeConverter.java new file mode 100644 index 0000000..bd1ce69 --- /dev/null +++ b/src/main/java/com/alvarium/serializers/ZonedDateTimeConverter.java @@ -0,0 +1,38 @@ + +/******************************************************************************* + * Copyright 2021 Dell Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + *******************************************************************************/ +package com.alvarium.serializers; + +import com.google.gson.*; + +import java.lang.reflect.Type; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +/** + * A converter of Instant datatype to RFC3339 string representation and vice versa + */ +public class ZonedDateTimeConverter implements JsonSerializer, JsonDeserializer { + + + public JsonElement serialize(ZonedDateTime src, Type typeOfSrc, JsonSerializationContext context) { + DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(src.getZone()); + return new JsonPrimitive(formatter.format(src)); + } + + @Override + public ZonedDateTime deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException { + return DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(json.getAsString(), ZonedDateTime::from); + } +} diff --git a/src/main/java/com/alvarium/utils/IDGenerator.java b/src/main/java/com/alvarium/utils/IDGenerator.java new file mode 100644 index 0000000..a36cbe1 --- /dev/null +++ b/src/main/java/com/alvarium/utils/IDGenerator.java @@ -0,0 +1,15 @@ +package com.alvarium.utils; + +import de.huxhorn.sulky.ulid.ULID; + +public class IDGenerator { + + private IDGenerator() {} + + private static final ULID ULID = new ULID(); + + public static String generate() { + return ULID.nextULID(); + } + +} diff --git a/src/test/java/com/alvarium/PublishWrapperTest.java b/src/test/java/com/alvarium/PublishWrapperTest.java index 441bf89..606fed7 100644 --- a/src/test/java/com/alvarium/PublishWrapperTest.java +++ b/src/test/java/com/alvarium/PublishWrapperTest.java @@ -15,6 +15,7 @@ package com.alvarium; import java.time.Instant; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -51,7 +52,7 @@ public void toJsonShouldParseAnnotationCorrectly() { AnnotationType.TPM, "signature", true, - Instant.now() + ZonedDateTime.now() ); final List annotations = List.of(annotation, annotation); final PublishWrapper wrapper = new PublishWrapper( diff --git a/src/test/java/com/alvarium/SdkTest.java b/src/test/java/com/alvarium/SdkTest.java index d6c84a7..4c21f8f 100644 --- a/src/test/java/com/alvarium/SdkTest.java +++ b/src/test/java/com/alvarium/SdkTest.java @@ -20,6 +20,7 @@ import java.nio.file.Paths; import java.util.HashMap; +import com.alvarium.hash.HashTypeException; import com.alvarium.utils.PropertyBag; import com.alvarium.annotators.Annotator; import com.alvarium.annotators.AnnotatorException; @@ -56,7 +57,7 @@ public void publish(byte[] data) { } public void close() { System.out.println("Connections closed"); - } + } } public class SdkTest { private final String testJson; @@ -71,7 +72,7 @@ public void instantiateSdkShouldNotThrow() throws AnnotatorException, StreamExce final SdkInfo sdkInfo = SdkInfo.fromJson(this.testJson); // init annotators - final Annotator[] annotators = new Annotator[sdkInfo.getAnnotators().length]; + final Annotator[] annotators = new Annotator[sdkInfo.getAnnotators().length]; final AnnotatorFactory annotatorFactory = new AnnotatorFactory(); // init logger @@ -87,7 +88,7 @@ public void instantiateSdkShouldNotThrow() throws AnnotatorException, StreamExce } @Test - public void createShouldReturnSameData() throws AnnotatorException, StreamException { + public void createShouldReturnSameData() throws AnnotatorException, StreamException, HashTypeException { final Sdk sdk = new MockSdk(); byte[] oldData = {0xA, 0x1}; byte[] newData = {0x1, 0xA}; @@ -97,7 +98,7 @@ public void createShouldReturnSameData() throws AnnotatorException, StreamExcept } @Test - public void defaultSdkShouldCreateAnnotations() throws AnnotatorException, StreamException { + public void defaultSdkShouldCreateAnnotations() throws AnnotatorException, StreamException, HashTypeException { final SdkInfo sdkInfo = SdkInfo.fromJson(this.testJson); // init annotators @@ -109,7 +110,7 @@ public void defaultSdkShouldCreateAnnotations() throws AnnotatorException, Strea Configurator.setRootLevel(Level.DEBUG); for (int i = 0; i < annotators.length; i++) { - annotators[i] = annotatorFactory.getAnnotator(sdkInfo.getAnnotators()[i], sdkInfo, logger); + annotators[i] = annotatorFactory.getAnnotator(sdkInfo.getAnnotators()[i], sdkInfo, logger); } final Sdk sdk = new DefaultSdk(annotators, sdkInfo, logger); @@ -122,19 +123,19 @@ public void defaultSdkShouldCreateAnnotations() throws AnnotatorException, Strea @Test public void defaultSdkShouldCreateTransitionAnnotations() throws AnnotatorException, - StreamException { + StreamException, HashTypeException { final SdkInfo sdkInfo = SdkInfo.fromJson(this.testJson); // init annotators final Annotator[] annotators = new Annotator[sdkInfo.getAnnotators().length]; final AnnotatorFactory annotatorFactory = new AnnotatorFactory(); - + // init logger final Logger logger = LogManager.getRootLogger(); Configurator.setRootLevel(Level.DEBUG); for (int i = 0; i < annotators.length; i++) { - annotators[i] = annotatorFactory.getAnnotator(sdkInfo.getAnnotators()[i], sdkInfo, logger); + annotators[i] = annotatorFactory.getAnnotator(sdkInfo.getAnnotators()[i], sdkInfo, logger); } final Sdk sdk = new DefaultSdk(annotators, sdkInfo, logger); @@ -146,7 +147,7 @@ public void defaultSdkShouldCreateTransitionAnnotations() throws AnnotatorExcept } @Test - public void defaultSdkShouldMutateData() throws AnnotatorException, StreamException { + public void defaultSdkShouldMutateData() throws AnnotatorException, StreamException, HashTypeException { final SdkInfo sdkInfo = SdkInfo.fromJson(this.testJson); // init annotators @@ -158,7 +159,7 @@ public void defaultSdkShouldMutateData() throws AnnotatorException, StreamExcept Configurator.setRootLevel(Level.DEBUG); for (int i = 0; i < annotators.length; i++) { - annotators[i] = annotatorFactory.getAnnotator(sdkInfo.getAnnotators()[i], sdkInfo, logger); + annotators[i] = annotatorFactory.getAnnotator(sdkInfo.getAnnotators()[i], sdkInfo, logger); } final Sdk sdk = new DefaultSdk(annotators, sdkInfo, logger); @@ -173,7 +174,7 @@ public void defaultSdkShouldMutateData() throws AnnotatorException, StreamExcept @Test public void defaultSdkShouldCreatePublishedAnnotations() throws AnnotatorException, - StreamException { + StreamException, HashTypeException { final SdkInfo sdkInfo = SdkInfo.fromJson(this.testJson); // init annotators @@ -185,7 +186,7 @@ public void defaultSdkShouldCreatePublishedAnnotations() throws AnnotatorExcepti Configurator.setRootLevel(Level.DEBUG); for (int i = 0; i < annotators.length; i++) { - annotators[i] = annotatorFactory.getAnnotator(sdkInfo.getAnnotators()[i], sdkInfo, logger); + annotators[i] = annotatorFactory.getAnnotator(sdkInfo.getAnnotators()[i], sdkInfo, logger); } final Sdk sdk = new DefaultSdk(annotators, sdkInfo, logger); diff --git a/src/test/java/com/alvarium/annotators/AnnotatorTest.java b/src/test/java/com/alvarium/annotators/AnnotatorTest.java index 3a36430..dfe3470 100644 --- a/src/test/java/com/alvarium/annotators/AnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/AnnotatorTest.java @@ -87,8 +87,8 @@ public void mockAnnotatorShouldReturnSatisfiedAnnotation() throws AnnotatorExcep final byte[] data = "test data".getBytes(); final PropertyBag ctx = new ImmutablePropertyBag(new HashMap<>()); - final Annotation satisfiedAnnotation = satisfiedAnnotator.execute(ctx, data); - final Annotation unsatisfiedAnnotation = unsatisfiedAnnotator.execute(ctx, data); + final Annotation satisfiedAnnotation = satisfiedAnnotator.execute(ctx, data, ""); + final Annotation unsatisfiedAnnotation = unsatisfiedAnnotator.execute(ctx, data, ""); assert satisfiedAnnotation.getIsSatisfied(); assert !unsatisfiedAnnotation.getIsSatisfied(); @@ -120,7 +120,7 @@ public void mockAnnotatorShouldReturnTag() throws AnnotatorException { final byte[] data = "test data".getBytes(); final PropertyBag ctx = new ImmutablePropertyBag(new HashMap<>()); - final Annotation noHashAnnotation = noHashAnnotator.execute(ctx, data); + final Annotation noHashAnnotation = noHashAnnotator.execute(ctx, data, ""); assert "".equals(noHashAnnotation.getTag()); } @@ -151,7 +151,7 @@ public void mockAnnotatorShouldReturnLayer() throws AnnotatorException { final byte[] data = "test data".getBytes(); final PropertyBag ctx = new ImmutablePropertyBag(new HashMap<>()); - final Annotation noHashAnnotation = noHashAnnotator.execute(ctx, data); + final Annotation noHashAnnotation = noHashAnnotator.execute(ctx, data, ""); assert LayerType.Application.equals(noHashAnnotation.getLayer()); } diff --git a/src/test/java/com/alvarium/annotators/ChecksumAnnotatorTest.java b/src/test/java/com/alvarium/annotators/ChecksumAnnotatorTest.java index 576ad8b..875c034 100644 --- a/src/test/java/com/alvarium/annotators/ChecksumAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/ChecksumAnnotatorTest.java @@ -102,14 +102,14 @@ public void executeShouldReturnAnnotation() throws AnnotatorException, HashTypeE ); byte[] data = "pipeline1/1".getBytes(); - Annotation annotation = annotator.execute(ctx, data); + Annotation annotation = annotator.execute(ctx, data, ""); System.out.println(annotation.toJson()); assert annotation.getIsSatisfied(); // change artifact checksum Files.write(checksumFile.toPath(), "bar".getBytes()); - annotation = annotator.execute(ctx, data); + annotation = annotator.execute(ctx, data, ""); System.out.println(annotation.toJson()); assert !annotation.getIsSatisfied(); diff --git a/src/test/java/com/alvarium/annotators/PkiAnnotatorTest.java b/src/test/java/com/alvarium/annotators/PkiAnnotatorTest.java index 0fe642d..15a6d3e 100644 --- a/src/test/java/com/alvarium/annotators/PkiAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/PkiAnnotatorTest.java @@ -69,7 +69,7 @@ public void executeShouldGetSatisfiedAnnotation() throws AnnotatorException { final AnnotatorConfig[] annotators = {pkiCfg}; final SdkInfo config = new SdkInfo(annotators, new HashInfo(HashType.SHA256Hash), sigInfo, null, LayerType.Application); final Annotator annotator = annotatorFactory.getAnnotator(pkiCfg, config, logger); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assertTrue("isSatisfied should be true", annotation.getIsSatisfied()); } @@ -99,7 +99,7 @@ public void executeShouldGetUnsatisfiedAnnotation() throws AnnotatorException { final SdkInfo config = new SdkInfo(annotators, new HashInfo(HashType.SHA256Hash), sigInfo, null, LayerType.Application); final Annotator annotator = annotatorFactory.getAnnotator(pkiCfg, config, logger); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assertFalse("isSatisfied should be false", annotation.getIsSatisfied()); } diff --git a/src/test/java/com/alvarium/annotators/PkiHttpAnnotatorTest.java b/src/test/java/com/alvarium/annotators/PkiHttpAnnotatorTest.java index 5c7eff6..7339ee0 100644 --- a/src/test/java/com/alvarium/annotators/PkiHttpAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/PkiHttpAnnotatorTest.java @@ -99,7 +99,7 @@ public void testAnnotationOK() throws AnnotatorException, RequestHandlerExceptio final AnnotatorConfig[] annotators = {annotatorInfo}; final SdkInfo config = new SdkInfo(annotators, new HashInfo(HashType.SHA256Hash), sigInfo, null, LayerType.Application); final Annotator annotator = annotatorFactory.getAnnotator(annotatorInfo, config, logger); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assertTrue("isSatisfied should be true", annotation.getIsSatisfied()); } @@ -131,7 +131,7 @@ public void testInvalidKeyType() throws AnnotatorException, RequestHandlerExcept final AnnotatorConfig[] annotators = {annotatorInfo}; final SdkInfo config = new SdkInfo(annotators, new HashInfo(HashType.SHA256Hash), sigInfo, null, LayerType.Application); final Annotator annotator = annotatorFactory.getAnnotator(annotatorInfo, config, logger); - annotator.execute(ctx, data); + annotator.execute(ctx, data, ""); } @Test @@ -160,7 +160,7 @@ public void testKeyNotFound() throws AnnotatorException, RequestHandlerException final AnnotatorConfig[] annotators = {annotatorInfo}; final SdkInfo config = new SdkInfo(annotators, new HashInfo(HashType.SHA256Hash), sigInfo, null, LayerType.Application); final Annotator annotator = annotatorFactory.getAnnotator(annotatorInfo, config, logger); - Annotation annotation = annotator.execute(ctx, data); + Annotation annotation = annotator.execute(ctx, data, ""); assertFalse("isSatisfied should be false", annotation.getIsSatisfied()); } @@ -188,7 +188,7 @@ public void testEmptySignature() throws AnnotatorException, RequestHandlerExcept final AnnotatorConfig[] annotators = {annotatorInfo}; final SdkInfo config = new SdkInfo(annotators, new HashInfo(HashType.SHA256Hash), sigInfo, null, LayerType.Application); final Annotator annotator = annotatorFactory.getAnnotator(annotatorInfo, config, logger); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assertFalse("isSatisfied should be false", annotation.getIsSatisfied()); } @@ -216,7 +216,7 @@ public void testInvalidSignature() throws AnnotatorException, RequestHandlerExce final AnnotatorConfig[] annotators = {annotatorInfo}; final SdkInfo config = new SdkInfo(annotators, new HashInfo(HashType.SHA256Hash), sigInfo, null, LayerType.Application); final Annotator annotator = annotatorFactory.getAnnotator(annotatorInfo, config, logger); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assertFalse("isSatisfied should be false", annotation.getIsSatisfied()); } diff --git a/src/test/java/com/alvarium/annotators/SbomAnnotatorTest.java b/src/test/java/com/alvarium/annotators/SbomAnnotatorTest.java index 8812615..2f2a6bd 100644 --- a/src/test/java/com/alvarium/annotators/SbomAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/SbomAnnotatorTest.java @@ -52,7 +52,7 @@ public void executeShouldReturnSatisfiedAnnotation() throws Exception { "./src/test/java/com/alvarium/annotators/sbom/spdx-valid.json" ); final PropertyBag ctx = new ImmutablePropertyBag(map); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assert annotation.getIsSatisfied(); } @@ -67,7 +67,7 @@ public void executeShouldReturnUnsatisfiedAnnotation() throws Exception { "./src/test/java/com/alvarium/annotators/sbom/spdx-valid.json" ); final PropertyBag ctx = new ImmutablePropertyBag(map); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assert !annotation.getIsSatisfied(); } diff --git a/src/test/java/com/alvarium/annotators/SourceAnnotatorTest.java b/src/test/java/com/alvarium/annotators/SourceAnnotatorTest.java index 20dbb88..f6fb664 100644 --- a/src/test/java/com/alvarium/annotators/SourceAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/SourceAnnotatorTest.java @@ -70,7 +70,7 @@ public void executeShouldReturnAnnotation() throws AnnotatorException, IOExcepti final byte[] data = "test data".getBytes(); final PropertyBag ctx = new ImmutablePropertyBag(new HashMap()); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); System.out.println(annotation.toJson()); } diff --git a/src/test/java/com/alvarium/annotators/SourceCodeAnnotatorTest.java b/src/test/java/com/alvarium/annotators/SourceCodeAnnotatorTest.java index 767be8b..298ddb9 100644 --- a/src/test/java/com/alvarium/annotators/SourceCodeAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/SourceCodeAnnotatorTest.java @@ -110,14 +110,14 @@ public void executeShouldReturnAnnotation() throws AnnotatorException, IOExcepti byte[] data = "pipeline1/1".getBytes(); - Annotation annotation = annotator.execute(ctx, data); + Annotation annotation = annotator.execute(ctx, data, ""); System.out.println(annotation.toJson()); assert annotation.getIsSatisfied(); // tamper with existing file in source code Files.write(f1.toPath(), "tampered".getBytes()); - annotation = annotator.execute(ctx, data); + annotation = annotator.execute(ctx, data, ""); System.out.println(annotation.toJson()); assert !annotation.getIsSatisfied(); diff --git a/src/test/java/com/alvarium/annotators/TlsAnnotatorTest.java b/src/test/java/com/alvarium/annotators/TlsAnnotatorTest.java index 1a6cd3a..e286416 100644 --- a/src/test/java/com/alvarium/annotators/TlsAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/TlsAnnotatorTest.java @@ -80,7 +80,7 @@ public void executeShouldReturnAnnotation() throws AnnotatorException, IOExcepti map.put(AnnotationType.TLS.name(), socket); final PropertyBag bag = new ImmutablePropertyBag(map); - final Annotation annotation = annotator.execute(bag, data); + final Annotation annotation = annotator.execute(bag, data, ""); System.out.println(annotation.toJson()); } } diff --git a/src/test/java/com/alvarium/annotators/TpmAnnotatorTest.java b/src/test/java/com/alvarium/annotators/TpmAnnotatorTest.java index 7b99ca3..bd9dd96 100644 --- a/src/test/java/com/alvarium/annotators/TpmAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/TpmAnnotatorTest.java @@ -68,7 +68,7 @@ public void executeShouldCreateAnnotation() throws AnnotatorException { PropertyBag ctx = new ImmutablePropertyBag(new HashMap()); byte[] data = {0x1, 0x2}; - Annotation annotation = tpm.execute(ctx, data); + Annotation annotation = tpm.execute(ctx, data, ""); System.out.println(annotation.toJson()); } diff --git a/src/test/java/com/alvarium/annotators/VulnerabilityAnnotatorTest.java b/src/test/java/com/alvarium/annotators/VulnerabilityAnnotatorTest.java index cf216f5..4929fd5 100644 --- a/src/test/java/com/alvarium/annotators/VulnerabilityAnnotatorTest.java +++ b/src/test/java/com/alvarium/annotators/VulnerabilityAnnotatorTest.java @@ -90,7 +90,7 @@ public void executeShouldReturnAnnotation() throws AnnotatorException, IOExcepti map.put(AnnotationType.VULNERABILITY.name(), pomXmlFile.toPath().getParent().toString()); final PropertyBag ctx = new ImmutablePropertyBag(map); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assert !annotation.getIsSatisfied(); } @@ -139,7 +139,7 @@ public void executeShouldReturnSatisfiedAnnotation() throws AnnotatorException, map.put(AnnotationType.VULNERABILITY.name(), pomXmlFile.toPath().getParent().toString()); final PropertyBag ctx = new ImmutablePropertyBag(map); - final Annotation annotation = annotator.execute(ctx, data); + final Annotation annotation = annotator.execute(ctx, data, ""); assert annotation.getIsSatisfied(); } diff --git a/src/test/java/com/alvarium/contracts/AnnotationListTest.java b/src/test/java/com/alvarium/contracts/AnnotationListTest.java index 2a11159..6668c73 100644 --- a/src/test/java/com/alvarium/contracts/AnnotationListTest.java +++ b/src/test/java/com/alvarium/contracts/AnnotationListTest.java @@ -19,12 +19,15 @@ import java.io.IOException; import java.time.Instant; +import java.time.ZonedDateTime; import java.util.List; import com.alvarium.hash.HashType; +import org.junit.Ignore; import org.junit.Test; +@Ignore public class AnnotationListTest { @Test @@ -37,7 +40,7 @@ public void toJsonShouldParseCorrectly() { AnnotationType.MOCK, "signature", true, - Instant.now() + ZonedDateTime.now() ); final AnnotationList annotations = new AnnotationList(List.of(annotation, annotation)); System.out.println(annotations.toJson()); diff --git a/src/test/java/com/alvarium/contracts/AnnotationTest.java b/src/test/java/com/alvarium/contracts/AnnotationTest.java index b079072..6de01b5 100644 --- a/src/test/java/com/alvarium/contracts/AnnotationTest.java +++ b/src/test/java/com/alvarium/contracts/AnnotationTest.java @@ -20,7 +20,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; -import java.time.Instant; +import java.time.*; import java.time.format.DateTimeFormatter; import com.alvarium.hash.HashType; @@ -28,38 +28,37 @@ import org.junit.Test; public class AnnotationTest { - private final String testJson; - private final Instant testTimestamp; - private final String testId; + private final String testJson; + private final ZonedDateTime testTimestamp; + private final String testId; - public AnnotationTest() throws IOException{ - String path = "./src/test/java/com/alvarium/contracts/data.json"; - testJson = Files.readString(Paths.get(path), StandardCharsets.US_ASCII); + public AnnotationTest() throws IOException { + String path = "./src/test/java/com/alvarium/contracts/data.json"; + testJson = Files.readString(Paths.get(path), StandardCharsets.US_ASCII); - testId = "01FE0RFFJY94R1ER2AM9BG63E2"; - testTimestamp = DateTimeFormatter.ISO_ZONED_DATE_TIME - .parse("2021-08-24T12:22:33.334070489-05:00", Instant::from); - } + testId = "01FE0RFFJY94R1ER2AM9BG63E2"; + testTimestamp = DateTimeFormatter.ISO_ZONED_DATE_TIME + .parse("2021-08-24T12:22:33.334070489-05:00", ZonedDateTime::from); + } - @Test - public void toJsonShouldReturnTheRightRepresentation() { - Annotation annotation = new Annotation("key", HashType.MD5Hash, "host", LayerType.Application, AnnotationType.TPM, - "signature", true, testTimestamp); - String result = annotation.toJson(); - System.out.println(result); - } - - @Test - public void fromJsonShouldReturnAnObjectWithTheRightProps() { + @Test + public void toJsonShouldReturnTheRightRepresentation() { + Annotation annotation = new Annotation("key", HashType.MD5Hash, "host", LayerType.Application, AnnotationType.TPM, + "signature", true, testTimestamp); + String result = annotation.toJson(); + System.out.println(result); + } - Annotation annotation = Annotation.fromJson(this.testJson); - assertEquals(this.testId, annotation.getId()); - assertEquals("320", annotation.getKey()); - assertEquals(HashType.MD5Hash, annotation.getHash()); - assertEquals("host", annotation.getHost()); - assertEquals(AnnotationType.TPM, annotation.getKind()); - assertEquals("test sign", annotation.getSignature()); - assertEquals(true, annotation.getIsSatisfied()); - assertEquals(testTimestamp, annotation.getTimestamp()); - } + @Test + public void fromJsonShouldReturnAnObjectWithTheRightProps() { + Annotation annotation = Annotation.fromJson(this.testJson); + assertEquals(this.testId, annotation.getId()); + assertEquals("320", annotation.getKey()); + assertEquals(HashType.MD5Hash, annotation.getHash()); + assertEquals("host", annotation.getHost()); + assertEquals(AnnotationType.TPM, annotation.getKind()); + assertEquals("test sign", annotation.getSignature()); + assertEquals(true, annotation.getIsSatisfied()); + assertEquals(testTimestamp, annotation.getTimestamp()); + } }