Skip to content

Commit

Permalink
Merge pull request #206 from ashok-ksharma/MOSIP-34253
Browse files Browse the repository at this point in the history
[MOSIP-34253] The code is modified to enable the static data share using configured policy without communicating to Policy Management and Key Management system
  • Loading branch information
vishwa-vyom authored Aug 9, 2024
2 parents fa2c6ca + 332ca83 commit 7b4df96
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.Map;

import io.mosip.commons.khazana.exception.ObjectStoreAdapterException;
import jakarta.annotation.PostConstruct;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -119,6 +120,13 @@ 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.standalone.mode.enabled:false}")
private boolean standaloneModeEnabled;

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

/** The Constant DATETIME_PATTERN. */
private static final String DATETIME_PATTERN = "mosip.data.share.datetime.pattern";
Expand All @@ -138,10 +146,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 policyPublishDate = null;
LOGGER.debug(LoggerFileConstant.SESSIONID.toString(), LoggerFileConstant.POLICYID.toString(),
"standaloneModeEnabled : " + standaloneModeEnabled + ", isSignatureDisabled : " + isSignatureDisabled);
if(!standaloneModeEnabled) {
PolicyResponseDto policyDetailResponse = policyUtil.getPolicyDetail(policyId, subscriberId);
dataSharePolicy = policyDetailResponse.getPolicies().getDataSharePolicies();
policyPublishDate = 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 @@ -162,10 +177,13 @@ public DataShare createDataShare(String policyId, String subscriberId, Multipart
.toISOString(DateUtils.addMinutes(DateUtils.parseUTCToDate(createShareTime),
Integer.parseInt(dataSharePolicy.getValidForInMinutes())));

String jwtSignature = digitalSignatureUtil.jwtSign(fileData, file.getName(), subscriberId,
createShareTime, expiryTime);
Map<String, Object> aclMap = prepareMetaData(subscriberId, policyId, policyDetailResponse,
jwtSignature);
String jwtSignature = "";
if(!isSignatureDisabled) {
jwtSignature = digitalSignatureUtil.jwtSign(fileData, file.getName(), subscriberId,
createShareTime, expiryTime);
}
Map<String, Object> aclMap = prepareMetaData(subscriberId, policyId, dataSharePolicy,
jwtSignature, policyPublishDate);
randomShareKey = storefile(aclMap, new ByteArrayInputStream(encryptedData), policyId, subscriberId);
String dataShareUrl = constructURL(randomShareKey, dataSharePolicy, policyId,
subscriberId);
Expand Down Expand Up @@ -325,17 +343,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 policyPublishDate 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 policyPublishDate) {

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

aclMap.put("policyid", policyId);
aclMap.put("policypublishdate", policyResponseDto.getPublishDate());
aclMap.put("policypublishdate", policyPublishDate);
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 @@ -3,7 +3,11 @@
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import io.mosip.datashare.dto.DataShareDto;
import jakarta.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
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 +54,22 @@ public class PolicyUtil {
@Autowired
private ObjectMapper mapper;

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

/** The static data share policy Json used for sharing the data. */
@Value("${mosip.data.share.static-policy.policy-json:#{null}}")
private String staticPolicyJson;

/** The static data share policyId used for sharing the data. */
@Value("${mosip.data.share.static-policy.policy-id:#{null}}")
private String staticPolicyId;

/** The static data share subscriberId used for sharing the data. */
@Value("${mosip.data.share.static-policy.subscriber-id:#{null}}")
private String staticSubscriberId;

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

Expand Down Expand Up @@ -108,4 +128,46 @@ 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 {
if (!policyId.equals(staticPolicyId) || !subscriberId.equals(staticSubscriberId))
throw new PolicyException("Either Policy Id or Subscriber Id not matching with configured in system");

DataShareDto dataShareDto = mapper.readValue(staticPolicyJson, 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 PolicyException)
throw (PolicyException)e;
throw new PolicyException(e);
}
}

/** This method validates the properties configured for the standalone mode for the data-share application.*/
@PostConstruct
private void validateStandaloneDataShareProperties() {
if(!standaloneModeEnabled) {
LOGGER.info("Application is running in integrated mode");
return;
}
LOGGER.info("Application is running in standalone mode");
if (StringUtils.isEmpty(staticPolicyId))
throw new PolicyException("Please configure the static data share policy Id");
if (StringUtils.isEmpty(staticSubscriberId))
throw new PolicyException("Please configure the static data share subscriber Id");
if (StringUtils.isEmpty(staticPolicyJson))
throw new PolicyException("Please configure the static data share policy");
}
}
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.PolicyException;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -240,4 +241,48 @@ 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, "standaloneModeEnabled", 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);
String policyId = "static-policyid";
String subscriberId = "static-subscriberid";
DataShare dataShare = dataShareServiceImpl.createDataShare(policyId, subscriberId, multiPartFile);
assertEquals("Data Share created successfully", policyId, dataShare.getPolicyId());
}

@Test(expected = PolicyException.class)
public void createStaticDataSharePolicyExceptionTest() {
ReflectionTestUtils.setField(dataShareServiceImpl, "standaloneModeEnabled", true);
Mockito.doThrow(new PolicyException()).
when(policyUtil).getStaticDataSharePolicy(Mockito.anyString(), Mockito.anyString());
dataShareServiceImpl.createDataShare(POLICY_ID, SUBSCRIBER_ID, multiPartFile);
}

@Test
public void disableSignatureSuccessTest() {
ReflectionTestUtils.setField(dataShareServiceImpl, "isSignatureDisabled", true);
DataShare dataShare = dataShareServiceImpl.createDataShare(POLICY_ID, SUBSCRIBER_ID, multiPartFile);
Mockito.verify(digitalSignatureUtil, Mockito.never()).jwtSign(Mockito.any(),
Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
assertEquals("Data Share created successfully", POLICY_ID, dataShare.getPolicyId());
}

@Test
public void enableSignatureSuccessTest() {
ReflectionTestUtils.setField(dataShareServiceImpl, "isSignatureDisabled", false);
DataShare dataShare = dataShareServiceImpl.createDataShare(POLICY_ID, SUBSCRIBER_ID, multiPartFile);
Mockito.verify(digitalSignatureUtil, Mockito.atLeastOnce()).jwtSign(Mockito.any(),
Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString());
assertEquals("Data Share created successfully", POLICY_ID, dataShare.getPolicyId());
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package io.mosip.datashare.test.util;

import static org.junit.Assert.assertEquals;

import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.JsonProcessingException;
import io.mosip.datashare.dto.DataShareDto;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -28,6 +31,7 @@
import io.mosip.datashare.util.PolicyUtil;
import io.mosip.datashare.util.RestUtil;
import io.mosip.kernel.core.exception.ServiceError;
import org.springframework.test.util.ReflectionTestUtils;

@RunWith(PowerMockRunner.class)
@PowerMockIgnore({ "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*", "org.w3c.dom.*",
Expand Down Expand Up @@ -96,4 +100,112 @@ public void policyFailureTest() throws JsonParseException, JsonMappingException,
policyManagerResponseDto.setErrors(errors);
policyUtil.getPolicyDetail("1234", "3456");
}

@Test
public void staticPolicyIdMissingTest() {
ReflectionTestUtils.setField(policyUtil, "standaloneModeEnabled", true);
Exception exception = assertThrows(PolicyException.class, () -> {
ReflectionTestUtils.invokeMethod(policyUtil,
"validateStandaloneDataShareProperties");
});
assertTrue(exception.getMessage().contains("DAT-SER-007"));
}

@Test
public void staticSubscriberIdMissingTest() {
ReflectionTestUtils.setField(policyUtil, "standaloneModeEnabled", true);
ReflectionTestUtils.setField(policyUtil, "staticPolicyId", "static-policyid");
Exception exception = assertThrows(PolicyException.class, () -> {
ReflectionTestUtils.invokeMethod(policyUtil,
"validateStandaloneDataShareProperties");
});
assertTrue(exception.getMessage().contains("DAT-SER-007"));
}

@Test
public void staticPolicyJsonMissingTest() {
ReflectionTestUtils.setField(policyUtil, "standaloneModeEnabled", true);
ReflectionTestUtils.setField(policyUtil, "staticPolicyId", "static-policyid");
ReflectionTestUtils.setField(policyUtil, "staticSubscriberId", "static-subscriberid");
Exception exception = assertThrows(PolicyException.class, () -> {
ReflectionTestUtils.invokeMethod(policyUtil,
"validateStandaloneDataShareProperties");
});
assertTrue(exception.getMessage().contains("DAT-SER-007"));
}

@Test
public void validateDataSharePropertiesWithStandaloneModeEnabled() {
ReflectionTestUtils.setField(policyUtil, "standaloneModeEnabled", true);
ReflectionTestUtils.setField(policyUtil, "staticPolicyId", "static-policyid");
ReflectionTestUtils.setField(policyUtil, "staticSubscriberId", "static-subscriberid");
ReflectionTestUtils.setField(policyUtil, "staticPolicyJson",
"{\"typeOfShare\":\"\",\"transactionsAllowed\":\"2\"," +
"\"shareDomain\":\"datashare.datashare\",\"encryptionType\":\"NONE\",\"source\":\"\",\"validForInMinutes\":\"30\"}");
ReflectionTestUtils.invokeMethod(policyUtil,
"validateStandaloneDataShareProperties");
}

@Test
public void validateDataSharePropertiesWithStandaloneModeDisabled() {
ReflectionTestUtils.setField(policyUtil, "standaloneModeEnabled", false);
ReflectionTestUtils.invokeMethod(policyUtil,
"validateStandaloneDataShareProperties");
}

@Test
public void staticPolicyIdNotMatchingWithRequest() {
ReflectionTestUtils.setField(policyUtil, "staticPolicyId", "static-policyid");
ReflectionTestUtils.setField(policyUtil, "staticSubscriberId", "static-subscriberid");
Exception exception = assertThrows(PolicyException.class, () -> {
policyUtil.getStaticDataSharePolicy("1234", "static-subscriberid");
});
assertTrue(exception.getMessage().contains("DAT-SER-007"));
}

@Test
public void staticSubscriberIdNotMatchingWithRequest() {
ReflectionTestUtils.setField(policyUtil, "staticPolicyId", "static-policyid");
ReflectionTestUtils.setField(policyUtil, "staticSubscriberId", "static-subscriberid");
Exception exception = assertThrows(PolicyException.class, () -> {
policyUtil.getStaticDataSharePolicy("static-policyid", "1234");
});
assertTrue(exception.getMessage().contains("DAT-SER-007"));
}

@Test
public void invalidStaticJsonPolicy() throws JsonProcessingException {
ReflectionTestUtils.setField(policyUtil, "standaloneModeEnabled", true);
ReflectionTestUtils.setField(policyUtil, "staticPolicyId", "static-policyid");
ReflectionTestUtils.setField(policyUtil, "staticSubscriberId", "static-subscriberid");
ReflectionTestUtils.setField(policyUtil, "staticPolicyJson",
"abc"); //Not a valid JSON
Mockito.when(objectMapper.readValue(Mockito.anyString(), Mockito.any(Class.class))).
thenThrow(new JsonParseException("Exception"));
Exception exception = assertThrows(PolicyException.class, () -> {
policyUtil.getStaticDataSharePolicy("static-policyid", "static-subscriberid");
});
assertTrue(exception.getMessage().contains("DAT-SER-007"));
}

@Test
public void getStaticDateSharePolicySuccessTest() throws JsonProcessingException {
ReflectionTestUtils.setField(policyUtil, "standaloneModeEnabled", true);
ReflectionTestUtils.setField(policyUtil, "staticPolicyId", "static-policyid");
ReflectionTestUtils.setField(policyUtil, "staticSubscriberId", "static-subscriberid");
ReflectionTestUtils.setField(policyUtil, "staticPolicyJson",
"{\"typeOfShare\":\"\",\"transactionsAllowed\":\"2\"," +
"\"shareDomain\":\"datashare.datashare\",\"encryptionType\":\"NONE\",\"source\":\"\",\"validForInMinutes\":\"30\"}");
DataShareDto dataShareDto = new DataShareDto();
dataShareDto.setTypeOfShare("");
dataShareDto.setTransactionsAllowed("2");
dataShareDto.setShareDomain("datashare.datashare");
dataShareDto.setEncryptionType("NONE");
dataShareDto.setSource("");
dataShareDto.setValidForInMinutes("30");
Mockito.when(objectMapper.readValue(Mockito.anyString(), Mockito.any(Class.class))).
thenReturn(dataShareDto);
DataShareDto response = policyUtil.getStaticDataSharePolicy("static-policyid", "static-subscriberid");
assertEquals(dataShareDto.getEncryptionType(), response.getEncryptionType());
}
}

0 comments on commit 7b4df96

Please sign in to comment.