Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[INJICERT-434] add preliminary VC 2.0 & VC 1.1 support via DataProvider plugin & VCFormatter + VCSigner #93

Merged
merged 21 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
488826b
[INJICERT-434] add DataProvider plugin interface
vharsh Sep 17, 2024
2109df3
[INJICERT-434] temp add sleep to replace JARs
vharsh Sep 18, 2024
7bd1820
[INJICERT-434] update interface definitions
vharsh Sep 19, 2024
22978d0
[INJICERT-434] add repository to fetch VC Templates
Piyush7034 Sep 19, 2024
8783f8a
[INJICERT-434] add prelimnary impl for VC template & sign
vharsh Sep 19, 2024
4b639a2
[INJICERT-434] add sample tests for templating
vharsh Sep 20, 2024
567bb7e
[INJICERT-434] fix TemplateRepository definition
vharsh Sep 23, 2024
87ab805
[INJICERT-434] generate RSA key for signing VCs
vharsh Sep 24, 2024
3dd2ae7
[INJICERT-434] fix local setup, update templates
vharsh Sep 25, 2024
d8cbfba
[INJICERT-497] use the correct plugin type for VCI resp
vharsh Oct 14, 2024
55e832e
[INJICERT-434] improve time handling iff DataProvider skips issuance/…
vharsh Oct 14, 2024
105787e
[INJICERT-434] get public key URL from config
vharsh Oct 14, 2024
aba0b06
[INJICERT-434] fix integration test
vharsh Oct 14, 2024
5922997
[INJICERT-434] separate CertifyPlugin & PluginIssuer VCIssuanceService
vharsh Oct 15, 2024
7818222
[INJICERT-434] add unit tests & refactor impl
vharsh Oct 17, 2024
dc52b1d
[INJICERT-434] add lib for json unit-test & update javadoc
vharsh Oct 17, 2024
0eed1ce
[INJICERT-434] add create & update TS to template_data table
vharsh Oct 17, 2024
a2f50b8
[INJICERT-434] add mandatory issuer property for DataProvider VC
vharsh Oct 17, 2024
847340e
[INJICERT-434] optimise imports
vharsh Oct 17, 2024
3962b33
[INJICERT-434] improve logging for keymanagerlib
vharsh Oct 17, 2024
0aba62d
[INJICERT-434] add redis pwd in cfg file
vharsh Oct 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions certify-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,41 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- templating dependencies -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-generic</artifactId>
<version>3.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ public class Constants {
public static final String CLIENT_ID = "client_id";
public static final String CERTIFY_PARTNER_APP_ID = "CERTIFY_PARTNER";
public static final String CERTIFY_SERVICE_APP_ID = "CERTIFY_SERVICE";
public static final String CERTIFY_MOCK_RSA = "CERTIFY_MOCK_RSA";
public static final String ROOT_KEY = "ROOT";
public static final String EMPTY_REF_ID = "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.mosip.certify.core.constants;

/**
* SignatureAlg is the constants file of supported VC sign algorithms.
* TODO(later): convert this into a structure such that it enables
* consumers to choose VC sign algos with
*/
public class SignatureAlg {
// LinkedDataSignature Algorithms
public static final String RSA_SIGNATURE_SUITE = "RsaSignature2018";

public static final String ED25519_SIGNATURE_SUITE = "Ed25519Signature2018";

// RS256, PS256, ES256 --> JWSAlgorithm.RS256.getName();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.mosip.certify.core.constants;

public class VCDM1Constants {
public static final String ISSUANCE_DATE = "issuanceDate";
public static final String EXPIRATION_DATE = "expirationDate";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.mosip.certify.core.constants;

/**
* VC Data Model 2.0 Constants are some constant fields for the (draft)
* VC DataModel 2.0.
* ref:
*/
public class VCDM2Constants {
public static final String VALID_UNITL = "validUntil";
public static final String VALID_FROM = "validFrom";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.mosip.certify.core.constants;

public class VCDMConstants {

// the below assertionMethods are common b/w VC 1.1 & VC 2.0
public static final String ASSERTION_METHOD = "assertionMethod";
public static final String PROOF = "proof";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.mosip.certify.core.entity;


import jakarta.persistence.Entity;
import jakarta.persistence.*;
import lombok.*;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;

@Entity
@NoArgsConstructor
@IdClass(TemplateId.class)
public class TemplateData {
@NotBlank(message = "Template is mandatory")
vharsh marked this conversation as resolved.
Show resolved Hide resolved
@Getter
@Setter
private String template;
@Id
@Getter
@Setter
private String context;
@Id
@Getter
@Setter
private String credentialType;

@NotBlank
@Column(name = "cr_dtimes")
private LocalDateTime createdTimes;

@Column(name = "upd_dtimes")
private LocalDateTime updatedTimes;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.mosip.certify.core.entity;

import lombok.*;

import java.io.Serializable;
import java.util.Objects;

@NoArgsConstructor
@AllArgsConstructor
public class TemplateId implements Serializable {
@Getter
@Setter
private String context;
@Getter
@Setter
private String credentialType;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TemplateId that)) return false;
return Objects.equals(context, that.context) && Objects.equals(credentialType, that.credentialType);
}

@Override
public int hashCode() {
return Objects.hash(context, credentialType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.mosip.certify.core.repository;

import io.mosip.certify.core.entity.TemplateData;
import io.mosip.certify.core.entity.TemplateId;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface TemplateRepository extends JpaRepository<TemplateData, TemplateId> {
Optional<TemplateData> findByCredentialTypeAndContext(String credentialType, String context);
// NOTE: best practice? .save()
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.mosip.certify.core.validators;

import io.mosip.certify.core.constants.VCFormats;
import io.mosip.certify.core.dto.CredentialDefinition;
import io.mosip.certify.core.dto.CredentialRequest;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;

public class CredentialRequestValidatorFactoryTest {

CredentialRequestValidatorFactory factory;

@Before
public void setUp() {
factory = new CredentialRequestValidatorFactory();
}

@Test
public void isValid_invalidFormat() {
CredentialRequest cr = new CredentialRequest();
cr.setFormat("fake-format");
assertFalse(factory.isValid(cr));
}

@Test
public void isValid_LDP_true() {
CredentialRequest cr = new CredentialRequest();
cr.setFormat(VCFormats.LDP_VC);
cr.setCredential_definition(new CredentialDefinition());
assertTrue(factory.isValid(cr));
}

@Test
public void isValid_mDoc_true() {
CredentialRequest cr = new CredentialRequest();
cr.setFormat(VCFormats.MSO_MDOC);
cr.setDoctype("mDoc-doctype-fake");
cr.setClaims(Map.of("isAge", "21"));
CredentialDefinition cd = new CredentialDefinition();
cd.setType(List.of("VerifiableCredential", "MockDrivingLicense"));
cd.setContext(List.of("https://example.context.page.sh"));
cr.setCredential_definition(new CredentialDefinition());
assertTrue(factory.isValid(cr));
}
}
38 changes: 38 additions & 0 deletions certify-core/src/test/resources/SchoolTemplate.vm
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#set($validFrom = $validFrom) ## Assume $validFrom might be null or undefined
#set($validUntil = $validUntil) ## Assume $validFrom might be null or undefined

{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"${context}"
],
"type": [
"VerifiableCredential",
"SchoolCertificate"
],
"validFrom": "${validFrom}",
"issuer": "${issuer}",
#if($validUntil)
"validUntil": "${validUntil}",
#end
"credentialSubject": {
"foundingDate": "${dob}",
"city": "${city}",
#if($amenities)
"amenities": #if($amenities)$amenities#else#set($amenities = '"[]"') $amenities#end,
#end
"name": "${name}",
"principalName": "${principalName}",
"schoolType": "${schoolType}",
"country": "${country}",
"schoolRegistrationNumber": "${policyName}"
},
"renderMethod": [{
"id": "https://vharsh.github.io/DID/insurance_svg_template.svg",
"type": "SvgRenderingTemplate",
"name": "Portrait Mode",
"css3MediaQuery": "@media (orientation: portrait)",
"digestMultibase": "zQmAPdhyxzznFCwYxAp2dRerWC85Wg6wFl9G270iEu5h6JqW"
}]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.mosip.certify.api.exception;

import io.mosip.certify.api.util.ErrorConstants;

/**
* {@link DataProviderExchangeException} is thrown when the DataProvider
* plugin fails to return user data against a set of claims generated by
* an Authentication provider.
*/
public class DataProviderExchangeException extends Exception {
private String errorCode;

public DataProviderExchangeException() {
super(ErrorConstants.VCI_DATAFETCH_FAILED);
this.errorCode = ErrorConstants.VCI_DATAFETCH_FAILED;
}

public DataProviderExchangeException(String errorCode) {
super(errorCode);
this.errorCode = errorCode;
}

public DataProviderExchangeException(String errorCode, String errorMessage) {
super(errorCode + " -> " + errorMessage);
this.errorCode = errorCode;
}

public String getErrorCode() {
return errorCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.mosip.certify.api.spi;

import io.mosip.certify.api.exception.DataProviderExchangeException;

import java.util.Map;

/**
* DataProviderPlugin is implemented by type#2 of identity plugin
* implementors to fetch data for Certify to template into a VC
* format of choice using {@link VCFormatter}.
*/
public interface DataProviderPlugin {
Map<String, Object> fetchData(Map<String, Object> identityDetails) throws DataProviderExchangeException;
jainhitesh9998 marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.mosip.certify.api.spi;


import java.util.Map;
/**
* VCDataModelFormatter is a templating engine which takes @param templateInput and returns a templated VC.
* Some implementations include
* - VC 2.0 data model templating engine
*/
public interface VCFormatter {
// TODO: Should it be changed to JSONObject?
String format(Map<String, Object> templateInput, Map<String, Object> defaultSettings);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.mosip.certify.api.spi;

import io.mosip.certify.api.dto.VCResult;
import java.util.Map;

/**
* VCSigner can sign any VC provided a vcHash & Signer inputs
*/
public interface VCSigner {
VCResult<?> perform(String templatedVC, Map<String, String> params);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public class ErrorConstants {

public static final String NOT_IMPLEMENTED = "not_implemented";
public static final String VCI_EXCHANGE_FAILED = "vci_exchange_failed";
public static final String VCI_DATAFETCH_FAILED = "vci_datafetch_failed";
}
5 changes: 4 additions & 1 deletion certify-service/configure_start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ download_and_extract() {

if [ "$enable_certify_artifactory" = "true" ]; then
download_and_extract "${artifactory_url_env}/artifactory/libs-release-local/certify/certify-plugin.zip" "${loader_path_env}"
echo "Please patch plugin JAR now"
sleep 60
echo "Plugin JAR patching not posssible now"
fi

#installs the pkcs11 libraries.
Expand Down Expand Up @@ -67,4 +70,4 @@ if [ "$download_hsm_client" = "true" ]; then
fi
cd $work_dir

exec "$@"
exec "$@"
6 changes: 6 additions & 0 deletions certify-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-assertj</artifactId>
<version>3.4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>info.weboftrust</groupId>
<artifactId>ld-signatures-java</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
vharsh marked this conversation as resolved.
Show resolved Hide resolved
import org.springframework.scheduling.annotation.EnableAsync;

@EnableAsync
@EnableCaching
@SpringBootApplication(scanBasePackages = "io.mosip.certify,"+
"io.mosip.certify.core.*," +
"io.mosip.kernel.crypto," +
"io.mosip.kernel.keymanager.hsm," +
"io.mosip.kernel.cryptomanager," +
Expand Down
Loading
Loading