Skip to content

Commit

Permalink
[MOSIP-34253] The code is modified to enable the static data share us…
Browse files Browse the repository at this point in the history
…ing configured policy without communicating to Policy Management and Key Management system.

Signed-off-by: Ashok Kumar Sharma <[email protected]>
  • Loading branch information
ashok-ksharma committed Jul 11, 2024
1 parent 54c9344 commit e6e0252
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ public enum DataUtilityErrorCodes {
SIGNATURE_EXCEPTION("DAT-SER-005", "Failed to generate digital signature"),
DATA_SHARE_NOT_FOUND_EXCEPTION("DAT-SER-008", "Data share not found"),
DATA_SHARE_EXPIRED_EXCEPTION("DAT-SER-006", "Data share usuage expired"),
POLICY_EXCEPTION("DAT-SER-007", "Exception while fetching policy details");
POLICY_EXCEPTION("DAT-SER-007", "Exception while fetching policy details"),
STATIC_DATA_SHARE_EXCEPTION("DAT-SER-008", "Exception while static data share");

private final String errorCode;
private final String errorMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Objects;
import java.util.stream.Collectors;

import io.mosip.datashare.exception.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.MediaType;
Expand All @@ -15,14 +16,6 @@
import io.mosip.datashare.controller.DataShareController;
import io.mosip.datashare.dto.DataShareResponseDto;
import io.mosip.datashare.dto.ErrorDTO;
import io.mosip.datashare.exception.ApiNotAccessibleException;
import io.mosip.datashare.exception.DataEncryptionFailureException;
import io.mosip.datashare.exception.DataShareExpiredException;
import io.mosip.datashare.exception.DataShareNotFoundException;
import io.mosip.datashare.exception.FileException;
import io.mosip.datashare.exception.PolicyException;
import io.mosip.datashare.exception.SignatureException;
import io.mosip.datashare.exception.URLCreationException;
import io.mosip.kernel.core.exception.BaseCheckedException;
import io.mosip.kernel.core.exception.BaseUncheckedException;
import io.mosip.kernel.core.util.DateUtils;
Expand Down Expand Up @@ -85,6 +78,12 @@ public ResponseEntity<DataShareResponseDto> policyException(PolicyException e) {
public ResponseEntity<DataShareResponseDto> objectStoreAdapterException(ObjectStoreAdapterException e) {
return buildDataShareApiExceptionResponse((Exception) e);
}

@ExceptionHandler(StaticDataShareException.class)
public ResponseEntity<DataShareResponseDto> staticDataShareException(StaticDataShareException e) {
return buildDataShareApiExceptionResponse((Exception) e);
}

private ResponseEntity<DataShareResponseDto> buildDataShareApiExceptionResponse(Exception ex) {
DataShareResponseDto response = new DataShareResponseDto();
Throwable e = ex;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.mosip.datashare.exception;

import io.mosip.datashare.constant.DataUtilityErrorCodes;
import io.mosip.kernel.core.exception.BaseUncheckedException;

public class StaticDataShareException extends BaseUncheckedException {

/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;

public StaticDataShareException() {
super();

}

public StaticDataShareException(String errorMessage) {
super(DataUtilityErrorCodes.STATIC_DATA_SHARE_EXCEPTION.getErrorCode(), errorMessage);
}

public StaticDataShareException(String message, Throwable cause) {
super(DataUtilityErrorCodes.STATIC_DATA_SHARE_EXCEPTION.getErrorCode() + EMPTY_SPACE, message, cause);

}

public StaticDataShareException(Throwable t) {
super(DataUtilityErrorCodes.STATIC_DATA_SHARE_EXCEPTION.getErrorCode(),
DataUtilityErrorCodes.STATIC_DATA_SHARE_EXCEPTION.getErrorMessage(), t);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ public class DataShareServiceImpl implements DataShareService {
@Value("${mosip.data.share.protocol}")
private String httpProtocol;

/** Defines whether static data share policy needs to be used for sharing the data*/
@Value("${mosip.data.share.static.share.enabled:false}")
private boolean staticShareEnabled;

/** The Constant DATETIME_PATTERN. */
private static final String DATETIME_PATTERN = "mosip.data.share.datetime.pattern";
Expand All @@ -138,10 +141,17 @@ public DataShare createDataShare(String policyId, String subscriberId, Multipart
String randomShareKey;
try {
byte[] fileData = file.getBytes();
PolicyResponseDto policyDetailResponse = policyUtil.getPolicyDetail(policyId, subscriberId);


DataShareDto dataSharePolicy = policyDetailResponse.getPolicies().getDataSharePolicies();
DataShareDto dataSharePolicy;
LocalDateTime publishDate = null;
LOGGER.debug(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.POLICYID.toString(),
"staticDataShareEnabled : " + staticShareEnabled);
if(!staticShareEnabled) {
PolicyResponseDto policyDetailResponse = policyUtil.getPolicyDetail(policyId, subscriberId);
dataSharePolicy = policyDetailResponse.getPolicies().getDataSharePolicies();
publishDate = policyDetailResponse.getPublishDate();
} else {
dataSharePolicy = policyUtil.getStaticDataSharePolicy(policyId, subscriberId);
}
byte[] encryptedData = null;
if (PARTNERBASED.equalsIgnoreCase(dataSharePolicy.getEncryptionType())) {
LOGGER.info(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.POLICYID.toString(),
Expand All @@ -164,8 +174,8 @@ public DataShare createDataShare(String policyId, String subscriberId, Multipart

String jwtSignature = digitalSignatureUtil.jwtSign(fileData, file.getName(), subscriberId,
createShareTime, expiryTime);
Map<String, Object> aclMap = prepareMetaData(subscriberId, policyId, policyDetailResponse,
jwtSignature);
Map<String, Object> aclMap = prepareMetaData(subscriberId, policyId, dataSharePolicy,
jwtSignature, publishDate);
randomShareKey = storefile(aclMap, new ByteArrayInputStream(encryptedData), policyId, subscriberId);
String dataShareUrl = constructURL(randomShareKey, dataSharePolicy, policyId,
subscriberId);
Expand Down Expand Up @@ -325,17 +335,18 @@ private boolean getAndUpdateMetaData(String randomShareKey, String policyId, Str
*
* @param subscriberId the subscriber id
* @param policyId the policy id
* @param policyDetailResponse the policy detail response
* @param dataSharePolicies the data share policies
* @param jwtSignature the jwt signature for shared object
* @param publishDate the policy publish date
* @return the map
*/
private Map<String, Object> prepareMetaData(String subscriberId, String policyId,
PolicyResponseDto policyResponseDto, String jwtSignature) {
DataShareDto dataSharePolicies, String jwtSignature, LocalDateTime publishDate) {

DataShareDto dataSharePolicies = policyResponseDto.getPolicies().getDataSharePolicies();
Map<String, Object> aclMap = new HashMap<>();

aclMap.put("policyid", policyId);
aclMap.put("policypublishdate", policyResponseDto.getPublishDate());
aclMap.put("policypublishdate", publishDate);
aclMap.put("subscriberId", subscriberId);
aclMap.put("validforinminutes", dataSharePolicies.getValidForInMinutes());
aclMap.put("transactionsallowed", dataSharePolicies.getTransactionsAllowed());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ public class DigitalSignatureUtil {
@Value("${mosip.data.share.digest.algorithm:SHA256}")
private String digestAlg;

/** Defines whether JWT signature generation needs to be disabled */
@Value("${mosip.data.share.signature.disabled:false}")
private boolean isSignatureDisabled;

/**
* Sign.
*
Expand All @@ -71,40 +75,45 @@ public String jwtSign(byte[] file, String filname, String partnerId, String crea
try {
LOGGER.debug(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.PARTNERID.toString(), partnerId,
"DigitalSignatureUtil::jwtSign()::entry");
String hashData = HMACUtils2.digestAsPlainText(file);
String digestData = CryptoUtil.encodeBase64(hashData.getBytes());

JSONObject signatureJson = createSignatureJson(filname, partnerId, digestData, creationTime, expiryTime);
String dataTobeSigned = mapper.writeValueAsString(signatureJson);
String encodedData = CryptoUtil.encodeBase64(dataTobeSigned.getBytes());
JWTSignatureRequestDto dto = new JWTSignatureRequestDto();
dto.setDataToSign(encodedData);
dto.setIncludeCertHash(
environment.getProperty("mosip.data.share.includeCertificateHash", Boolean.class));
dto.setIncludeCertificate(
environment.getProperty("mosip.data.share.includeCertificate", Boolean.class));
dto.setIncludePayload(environment.getProperty("mosip.data.share.includePayload", Boolean.class));
String certificateUrl = environment.getProperty("mosip.data.share.certificateurl");
if (StringUtils.isNotEmpty(certificateUrl)) {
dto.setCertificateUrl(certificateUrl);
}

RequestWrapper<JWTSignatureRequestDto> request = new RequestWrapper<>();
request.setRequest(dto);
request.setMetadata(null);
DateTimeFormatter format = DateTimeFormatter.ofPattern(environment.getProperty(DATETIME_PATTERN));
LocalDateTime localdatetime = LocalDateTime
.parse(DateUtils.getUTCCurrentDateTimeString(environment.getProperty(DATETIME_PATTERN)), format);
request.setRequesttime(localdatetime);
String responseString = restUtil.postApi(ApiName.KEYMANAGER_JWTSIGN, null, "", "",
MediaType.APPLICATION_JSON, request, String.class);

SignResponseDto responseObject = mapper.readValue(responseString, SignResponseDto.class);
if (responseObject != null && responseObject.getErrors() != null && !responseObject.getErrors().isEmpty()) {
ServiceError error = responseObject.getErrors().get(0);
throw new SignatureException(error.getMessage());
String signedData = "";
LOGGER.debug(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.PARTNERID.toString(), partnerId,
"isSignatureDisabled : " + isSignatureDisabled);
if(!isSignatureDisabled) {
String hashData = HMACUtils2.digestAsPlainText(file);
String digestData = CryptoUtil.encodeBase64(hashData.getBytes());

JSONObject signatureJson = createSignatureJson(filname, partnerId, digestData, creationTime, expiryTime);
String dataTobeSigned = mapper.writeValueAsString(signatureJson);
String encodedData = CryptoUtil.encodeBase64(dataTobeSigned.getBytes());
JWTSignatureRequestDto dto = new JWTSignatureRequestDto();
dto.setDataToSign(encodedData);
dto.setIncludeCertHash(
environment.getProperty("mosip.data.share.includeCertificateHash", Boolean.class));
dto.setIncludeCertificate(
environment.getProperty("mosip.data.share.includeCertificate", Boolean.class));
dto.setIncludePayload(environment.getProperty("mosip.data.share.includePayload", Boolean.class));
String certificateUrl = environment.getProperty("mosip.data.share.certificateurl");
if (StringUtils.isNotEmpty(certificateUrl)) {
dto.setCertificateUrl(certificateUrl);
}

RequestWrapper<JWTSignatureRequestDto> request = new RequestWrapper<>();
request.setRequest(dto);
request.setMetadata(null);
DateTimeFormatter format = DateTimeFormatter.ofPattern(environment.getProperty(DATETIME_PATTERN));
LocalDateTime localdatetime = LocalDateTime
.parse(DateUtils.getUTCCurrentDateTimeString(environment.getProperty(DATETIME_PATTERN)), format);
request.setRequesttime(localdatetime);
String responseString = restUtil.postApi(ApiName.KEYMANAGER_JWTSIGN, null, "", "",
MediaType.APPLICATION_JSON, request, String.class);

SignResponseDto responseObject = mapper.readValue(responseString, SignResponseDto.class);
if (responseObject != null && responseObject.getErrors() != null && !responseObject.getErrors().isEmpty()) {
ServiceError error = responseObject.getErrors().get(0);
throw new SignatureException(error.getMessage());
}
signedData = responseObject.getResponse().getJwtSignedData();
}
String signedData = responseObject.getResponse().getJwtSignedData();

LOGGER.debug(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.PARTNERID.toString(), partnerId,
"DigitalSignatureUtil::jwtSign()::exit");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.HashMap;
import java.util.Map;

import io.mosip.datashare.dto.DataShareDto;
import io.mosip.datashare.exception.StaticDataShareException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
Expand Down Expand Up @@ -50,6 +52,15 @@ public class PolicyUtil {
@Autowired
private ObjectMapper mapper;

/** The static data share policy used for sharing the data. */
private static final String STATIC_DATA_SHARE_POLICY = "mosip.data.share.static.share.policy";

/** The static data share policy used for sharing the data. */
private static final String STATIC_DATA_SHARE_POLICY_ID = "mosip.data.share.static.share.policyid";

/** The static data share policy used for sharing the data. */
private static final String STATIC_DATA_SHARE_SUBSCRIBER_ID = "mosip.data.share.static.share.subscriberid";

@Cacheable(value = "partnerpolicyCache", key = "#policyId + '_' + #subscriberId")
public PolicyResponseDto getPolicyDetail(String policyId, String subscriberId) {

Expand Down Expand Up @@ -108,4 +119,42 @@ public void emptyPartnerPolicyCache() {

}

/**
* Provides static data share policy for sharing the data.
* @param policyId Policy Id from request
* @param subscriberId Subscriber Id from request
* @return the DataShareDto object
*/
public DataShareDto getStaticDataSharePolicy(String policyId, String subscriberId) {
LOGGER.debug(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.POLICYID.toString(),
policyId, "PolicyUtil::getStaticDataSharePolicy()::entry");
try {
String staticPolicyId = env.getProperty(STATIC_DATA_SHARE_POLICY_ID);
if (staticPolicyId == null)
throw new StaticDataShareException("Please configure the static data share policy Id");

String staticSubscriberId = env.getProperty(STATIC_DATA_SHARE_SUBSCRIBER_ID);
if (staticSubscriberId == null)
throw new StaticDataShareException("Please configure the static data share subscriber Id");

if (!staticPolicyId.equals(policyId) || !staticSubscriberId.equals(subscriberId))
throw new StaticDataShareException("Either Policy Id or Subscriber Id not matching with configured in system");

String staticSharePolicy = env.getProperty(STATIC_DATA_SHARE_POLICY);
if (staticSharePolicy == null)
throw new StaticDataShareException("Please configure the static data share policy");

DataShareDto dataShareDto = mapper.readValue(staticSharePolicy, DataShareDto.class);
LOGGER.debug(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.POLICYID.toString(), policyId,
"PolicyUtil::getStaticDataSharePolicy()::exit");
return dataShareDto;
} catch (Exception e) {
LOGGER.error(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.POLICYID.toString(),
policyId,
"PolicyUtil::getStaticDataSharePolicy():: error with error message" + ExceptionUtils.getStackTrace(e));
if(e instanceof StaticDataShareException)
throw (StaticDataShareException)e;
throw new StaticDataShareException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
spring.cloud.config.uri=http://localhost:51000/config
spring.cloud.config.label=master
spring.application.name=application,data-share
#If active profiles are defined as a,b then profile b overrides the changes of a.
#Add the "standalone" profile in active profiles to enable data share using static policy.
#Check data-share-standalone.properties for reference.
spring.profiles.active=default
spring.cloud.config.name=data-share,application
management.endpoint.health.show-details=always
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.Map;

import io.mosip.commons.khazana.exception.ObjectStoreAdapterException;
import io.mosip.datashare.exception.StaticDataShareException;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -240,4 +241,28 @@ public void getDataFileDataShareNotFoundExceptionTest() {
Mockito.doThrow(new ObjectStoreAdapterException(OBJECT_STORE_NOT_ACCESSIBLE.getErrorCode(), OBJECT_STORE_NOT_ACCESSIBLE.getErrorMessage(), new Throwable())).when(objectStoreAdapter).getObject(Mockito.anyString(),Mockito.anyString(),Mockito.any(),Mockito.any(),Mockito.anyString());
dataShareServiceImpl.getDataFile("12dfsdff");
}

@Test
public void createStaticDataShareSuccessTest() {
ReflectionTestUtils.setField(dataShareServiceImpl, "staticShareEnabled", true);
DataShareDto dataShareDto = new DataShareDto();
dataShareDto.setTypeOfShare("");
dataShareDto.setTransactionsAllowed("2");
dataShareDto.setShareDomain("datashare.datashare");
dataShareDto.setEncryptionType("NONE");
dataShareDto.setSource("");
dataShareDto.setValidForInMinutes("30");
Mockito.when(policyUtil.getStaticDataSharePolicy(Mockito.anyString(), Mockito.anyString()))
.thenReturn(dataShareDto);
DataShare dataShare = dataShareServiceImpl.createDataShare(POLICY_ID, SUBSCRIBER_ID, multiPartFile);
assertEquals("Data Share created successfully", POLICY_ID, dataShare.getPolicyId());
}
@Test(expected = StaticDataShareException.class)
public void staticDateShareExceptionTest() {
ReflectionTestUtils.setField(dataShareServiceImpl, "staticShareEnabled", true);
Mockito.doThrow(new StaticDataShareException()).
when(policyUtil).getStaticDataSharePolicy(Mockito.anyString(), Mockito.anyString());
dataShareServiceImpl.createDataShare(POLICY_ID, SUBSCRIBER_ID, multiPartFile);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,13 @@ public void signFailureTest() throws JsonParseException, JsonMappingException, I

String signedData = digitalSignatureUtil.jwtSign(sample, "test", "", "", "");
}

@Test
public void disableSignatureSuccessTest() throws IOException {
String test = "testdata";
byte[] sample = test.getBytes();
ReflectionTestUtils.setField(digitalSignatureUtil, "isSignatureDisabled", true);
String signedData = digitalSignatureUtil.jwtSign(sample, "test", "", "", "");
assertEquals("", signedData);
}
}
Loading

0 comments on commit e6e0252

Please sign in to comment.