From 5e6a277185fb7fefe5551d31a050852fa54905b8 Mon Sep 17 00:00:00 2001 From: Markus Gylling Date: Wed, 31 Aug 2022 19:48:29 +0200 Subject: [PATCH] clean up endorsementinspector --- .../inspect/vc/EndorsementInspector.java | 62 +++++++------------ .../oneedtech/inspect/vc/OB30Inspector.java | 4 +- .../inspect/vc/probe/ProofVerifierProbe.java | 2 +- .../inspect/vc/probe/TypePropertyProbe.java | 55 ++++++++-------- 4 files changed, 53 insertions(+), 70 deletions(-) diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/EndorsementInspector.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/EndorsementInspector.java index 9f5f351..9801fc7 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/EndorsementInspector.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/EndorsementInspector.java @@ -1,10 +1,10 @@ package org.oneedtech.inspect.vc; import static java.lang.Boolean.TRUE; - import static org.oneedtech.inspect.core.probe.RunContext.Key.*; -import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT; import static org.oneedtech.inspect.core.report.ReportUtil.onProbeException; +import static org.oneedtech.inspect.util.code.Defensives.checkNotNull; +import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT; import java.net.URI; import java.util.ArrayList; @@ -17,19 +17,17 @@ import org.oneedtech.inspect.core.probe.GeneratedObject; import org.oneedtech.inspect.core.probe.Probe; import org.oneedtech.inspect.core.probe.RunContext; import org.oneedtech.inspect.core.probe.json.JsonPathEvaluator; -import org.oneedtech.inspect.core.probe.json.JsonSchemaProbe; import org.oneedtech.inspect.core.report.Report; import org.oneedtech.inspect.core.report.ReportItems; -import org.oneedtech.inspect.schema.SchemaKey; import org.oneedtech.inspect.util.json.ObjectMapperCache; import org.oneedtech.inspect.util.resource.Resource; import org.oneedtech.inspect.util.resource.UriResource; import org.oneedtech.inspect.util.resource.context.ResourceContext; import org.oneedtech.inspect.vc.Credential.Type; -import org.oneedtech.inspect.vc.probe.CredentialParseProbe; import org.oneedtech.inspect.vc.probe.ExpirationVerifierProbe; import org.oneedtech.inspect.vc.probe.InlineJsonSchemaProbe; import org.oneedtech.inspect.vc.probe.IssuanceVerifierProbe; +import org.oneedtech.inspect.vc.probe.ProofVerifierProbe; import org.oneedtech.inspect.vc.probe.RevocationListProbe; import org.oneedtech.inspect.vc.probe.SignatureVerifierProbe; import org.oneedtech.inspect.vc.probe.TypePropertyProbe; @@ -49,63 +47,47 @@ public class EndorsementInspector extends VCInspector implements SubInspector { @Override public Report run(Resource resource, Map parentObjects) { + /* * The resource param is the top-level credential that embeds the endorsement, we - * expect parentObjects to provide a pointer to the JsonNode we should check + * expect parentObjects to provide a pointer to the JsonNode we should check. + * + * The parent inspector is responsible to decode away possible jwt-ness, so that + * what we get here is a verbatim json node. + * */ - Credential verifiableCredential = (Credential) parentObjects.get(ENDORSEMENT_KEY); + Credential endorsement = (Credential) checkNotNull(parentObjects.get(ENDORSEMENT_KEY)); + ObjectMapper mapper = ObjectMapperCache.get(DEFAULT); JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper); RunContext ctx = new RunContext.Builder() .put(this) - .put(resource) .put(JACKSON_OBJECTMAPPER, mapper) .put(JSONPATH_EVALUATOR, jsonPath) - .put(ENDORSEMENT_KEY, verifiableCredential) .build(); List accumulator = new ArrayList<>(); int probeCount = 0; - try { - //detect type (png, svg, json, jwt) and extract json data - probeCount++; - accumulator.add(new CredentialParseProbe().run(resource, ctx)); - if(broken(accumulator)) return abort(ctx, accumulator, probeCount); - - //we expect the above to place a generated object in the context - Credential crd = ctx.getGeneratedObject(Credential.ID); - + //type property probeCount++; - accumulator.add(new TypePropertyProbe(Type.ClrCredential).run(crd.getJson(), ctx)); + accumulator.add(new TypePropertyProbe(Type.EndorsementCredential).run(endorsement.getJson(), ctx)); if(broken(accumulator)) return abort(ctx, accumulator, probeCount); - //canonical schema and inline schema - SchemaKey schema = crd.getSchemaKey().orElseThrow(); - for(Probe probe : List.of(new JsonSchemaProbe(schema), new InlineJsonSchemaProbe(schema))) { - probeCount++; - accumulator.add(probe.run(crd.getJson(), ctx)); - if(broken(accumulator)) return abort(ctx, accumulator, probeCount); - } - + //inline schema (parent inspector has already validated against canonical) + accumulator.add(new InlineJsonSchemaProbe().run(endorsement.getJson(), ctx)); + //signatures, proofs probeCount++; - if(crd.getJwt().isPresent()){ + if(endorsement.getJwt().isPresent()){ //The credential originally contained in a JWT, validate the jwt and external proof. - accumulator.add(new SignatureVerifierProbe().run(crd, ctx)); + accumulator.add(new SignatureVerifierProbe().run(endorsement, ctx)); } else { //The credential not contained in a jwt, must have an internal proof. - //TODO: @Miles Need to fix the issuer, Same as with outer CLR - //Swap -> "verificationMethod": "https://example.edu/issuers/565049#z6MkwA1498JfoCS3y4y3zggBDAosQEoCi5gsYH2PMXh1cFWK", - //To be like -> "verificationMethod": "did:key:z6MkkUD3J14nkYzn46QeuaVSnp7dF85QJKwKvJvfsjx79aXj", - //...but also work properly which old record seems not be doing... - - /* - accumulator.add(new ProofVerifierProbe().run(crd, ctx)); - */ + accumulator.add(new ProofVerifierProbe().run(endorsement, ctx)); } if(broken(accumulator)) return abort(ctx, accumulator, probeCount); @@ -113,7 +95,7 @@ public class EndorsementInspector extends VCInspector implements SubInspector { //check refresh service if we are not already refreshed (check just like in external CLR) probeCount++; if(resource.getContext().get(REFRESHED) != TRUE) { - Optional newID = checkRefreshService(crd, ctx); + Optional newID = checkRefreshService(endorsement, ctx); if(newID.isPresent()) { //TODO resource.type return this.run( @@ -122,11 +104,11 @@ public class EndorsementInspector extends VCInspector implements SubInspector { } } - //revocation, expiration and issuance (check just like in external CLR) + //revocation, expiration and issuance for(Probe probe : List.of(new RevocationListProbe(), new ExpirationVerifierProbe(), new IssuanceVerifierProbe())) { probeCount++; - accumulator.add(probe.run(crd, ctx)); + accumulator.add(probe.run(endorsement, ctx)); if(broken(accumulator)) return abort(ctx, accumulator, probeCount); } diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java index 13e58ac..8f8d07a 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/OB30Inspector.java @@ -141,7 +141,7 @@ public class OB30Inspector extends VCInspector { //embedded endorsements EndorsementInspector endorsementInspector = new EndorsementInspector.Builder().build(); - List endorsements = asNodeList(crd.getJson(), "$..endorsement", jsonPath); + List endorsements = asNodeList(crd.getJson(), "$..endorsement", jsonPath); for(JsonNode node : endorsements) { probeCount++; Credential endorsement = new Credential(resource, node); @@ -149,7 +149,7 @@ public class OB30Inspector extends VCInspector { } //embedded jwt endorsements - endorsements = asNodeList(crd.getJson(), "$..endorsementJwt", jsonPath); + endorsements = asNodeList(crd.getJson(), "$..endorsementJwt", jsonPath); for(JsonNode node : endorsements) { probeCount++; String jwt = node.asText(); diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ProofVerifierProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ProofVerifierProbe.java index c0bb34c..676a0a6 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ProofVerifierProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/ProofVerifierProbe.java @@ -51,7 +51,7 @@ public class ProofVerifierProbe extends Probe { } catch (DocumentError e) { return error(e.getType() + " " + e.getSubject(), ctx); } catch (VerificationError e) { - System.err.println(e.getCode()); + //System.err.println(e.getCode() + " (ProofVerifierProbe)"); if(e.getCode() == Code.Internal) { return exception(e.getMessage(), ctx.getResource()); } else if(e.getCode().equals(Code.Expired)) { diff --git a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java index 3c17f25..804380e 100644 --- a/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java +++ b/inspector-vc/src/main/java/org/oneedtech/inspect/vc/probe/TypePropertyProbe.java @@ -15,49 +15,50 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; /** - * A Probe that verifies a credential's type property. + * A Probe that verifies a credential's type property. + * * @author mgylling */ public class TypePropertyProbe extends Probe { private final Credential.Type expected; - + public TypePropertyProbe(Credential.Type expected) { super(ID); this.expected = checkNotNull(expected); } - + @Override public ReportItems run(JsonNode root, RunContext ctx) throws Exception { - ArrayNode typeNode = (ArrayNode)root.get("type"); - if(typeNode == null) return fatal("No type property", ctx); - + ArrayNode typeNode = (ArrayNode) root.get("type"); + if (typeNode == null) + return fatal("No type property", ctx); + List values = JsonNodeUtil.asStringList(typeNode); - - if(!values.contains("VerifiableCredential")) { + + if (!values.contains("VerifiableCredential")) { return fatal("The type property does not contain the entry 'VerifiableCredential'", ctx); } - - if(expected == Credential.Type.OpenBadgeCredential) { - if(!values.contains("OpenBadgeCredential") && !values.contains("AchievementCredential")) { - return fatal( - "The type property does not contain one of 'OpenBadgeCredential' or 'AchievementCredential'", - ctx); - } - } - else if(expected == Credential.Type.ClrCredential){ - if(!values.contains("ClrCredential")) { - return fatal( - "The type property does not contain the entry 'ClrCredential'", - ctx); - } + + if (expected == Credential.Type.OpenBadgeCredential) { + if (!values.contains("OpenBadgeCredential") && !values.contains("AchievementCredential")) { + return fatal("The type property does not contain one of 'OpenBadgeCredential' or 'AchievementCredential'", ctx); + } + } else if (expected == Credential.Type.ClrCredential) { + if (!values.contains("ClrCredential")) { + return fatal("The type property does not contain the entry 'ClrCredential'", ctx); + } + } else if (expected == Credential.Type.EndorsementCredential) { + if (!values.contains("EndorsementCredential")) { + return fatal("The type property does not contain the entry 'EndorsementCredential'", ctx); + } } else { - //TODO implement - throw new IllegalStateException(); + // TODO implement + throw new IllegalStateException(); } - + return success(ctx); } - - public static final String ID = TypePropertyProbe.class.getSimpleName(); + + public static final String ID = TypePropertyProbe.class.getSimpleName(); }