Skip to content

Commit 975107c

Browse files
authored
MOSIP-40926: building chain for partner certificate for 1.1.5.5 branch (#367)
* MOSIP-40926: building chain for partner certificate for 1.1.5.5 branch Signed-off-by: nagendra0721 <nagendra0718@gmail.com> * MOSIP-40926: upload certificate bug fix in 1.1.5.5 branch Signed-off-by: nagendra0721 <nagendra0718@gmail.com> * MOSIP-40926: update the roles Signed-off-by: nagendra0721 <nagendra0718@gmail.com> --------- Signed-off-by: nagendra0721 <nagendra0718@gmail.com>
1 parent 6736d27 commit 975107c

6 files changed

Lines changed: 186 additions & 27 deletions

File tree

kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/partnercertservice/constant/PartnerCertManagerConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,9 @@ public interface PartnerCertManagerConstants {
7676
String HASH_SHA2 = "SHA2";
7777

7878
int YEAR_DAYS = 365;
79+
80+
String FTM_PARTNER_DOMAIN = "FTM";
81+
82+
String ROOT_APP_ID = "ROOT";
83+
7984
}

kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/partnercertservice/controller/PartnerCertManagerController.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import javax.validation.Valid;
44

55
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.security.access.prepost.PreAuthorize;
67
import org.springframework.web.bind.annotation.CrossOrigin;
78
import org.springframework.web.bind.annotation.GetMapping;
89
import org.springframework.web.bind.annotation.PathVariable;
@@ -50,8 +51,7 @@ public class PartnerCertManagerController {
5051
* @param caCertRequestDto {@link CACertificateRequestDto} request
5152
* @return {@link CACertficateResponseDto} Upload Success
5253
*/
53-
// @PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL',
54-
// 'PMS_ADMIN')")
54+
@PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL','PMS_ADMIN','PARTNER_ADMIN','POLICYMANAGER')")
5555
@ResponseFilter
5656
@PostMapping(value = "/uploadCACertificate", produces = "application/json")
5757
public ResponseWrapper<CACertificateResponseDto> uploadCACertificate(
@@ -68,8 +68,7 @@ public ResponseWrapper<CACertificateResponseDto> uploadCACertificate(
6868
* @param partnerCertRequestDto {@link PartnerCertificateRequestDto} request
6969
* @return {@link PartnerCertificateResponseDto} signed certificate response
7070
*/
71-
// @PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL',
72-
// 'ID_AUTHENTICATION', 'PMS_USER')")
71+
@PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL','ID_AUTHENTICATION','PMS_USER','PMS_ADMIN','PARTNER_ADMIN','POLICYMANAGER')")
7372
@ResponseFilter
7473
@PostMapping(value = "/uploadPartnerCertificate", produces = "application/json")
7574
public ResponseWrapper<PartnerCertificateResponseDto> uploadPartnerCertificate(
@@ -80,14 +79,30 @@ public ResponseWrapper<PartnerCertificateResponseDto> uploadPartnerCertificate(
8079
return response;
8180
}
8281

82+
/**
83+
* To Upload Partner Certificate.
84+
*
85+
* @param partnerCertRequestDto {@link PartnerCertificateRequestDto} request
86+
* @return {@link PartnerCertificateResponseDto} signed certificate response
87+
*/
88+
@PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL','ID_AUTHENTICATION','PMS_USER','PMS_ADMIN','PARTNER_ADMIN','POLICYMANAGER')")
89+
@ResponseFilter
90+
@PostMapping(value = "/v2/uploadPartnerCertificate", produces = "application/json")
91+
public ResponseWrapper<PartnerCertificateResponseDto> uploadPartnerCertificateV2(
92+
@ApiParam("Upload Partner Certificates.") @RequestBody @Valid RequestWrapper<PartnerCertificateRequestDto> partnerCertRequestDto) {
93+
94+
ResponseWrapper<PartnerCertificateResponseDto> response = new ResponseWrapper<>();
95+
response.setResponse(partnerCertManagerService.uploadPartnerCertificateV2(partnerCertRequestDto.getRequest()));
96+
return response;
97+
}
98+
8399
/**
84100
* To Download Partner Certificate.
85101
*
86102
* @param certDownloadRequestDto {@link PartnerCertDownloadRequestDto} request
87103
* @return {@link PartnerCertDownloadResponeDto} encrypted Data
88104
*/
89-
// @PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL',
90-
// 'ID_AUTHENTICATION', 'PMS_USER')")
105+
@PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL','ID_AUTHENTICATION','PMS_USER','PMS_ADMIN','PARTNER_ADMIN','POLICYMANAGER')")
91106
@ResponseFilter
92107
@GetMapping(value = "/getPartnerCertificate/{partnerCertId}")
93108
public ResponseWrapper<PartnerCertDownloadResponeDto> getPartnerCertificate(
@@ -105,8 +120,7 @@ public ResponseWrapper<PartnerCertDownloadResponeDto> getPartnerCertificate(
105120
* @param certificateTrustRequestDto {@CertificateTrustRequestDto CertificateTrustDto} request
106121
* @return {@link CertificateTrustResponeDto} certificate verify response
107122
*/
108-
// @PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL',
109-
// 'ID_AUTHENTICATION', 'PMS_USER')")
123+
@PreAuthorize("hasAnyRole('ZONAL_ADMIN','GLOBAL_ADMIN','INDIVIDUAL','ID_AUTHENTICATION','PMS_USER','PMS_ADMIN','PARTNER_ADMIN','POLICYMANAGER')")
110124
@ResponseFilter
111125
@PostMapping(value = "/verifyCertificateTrust", produces = "application/json")
112126
public ResponseWrapper<CertificateTrustResponeDto> verifyCertificateTrust(

kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/partnercertservice/helper/PartnerCertManagerDBHelper.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.security.cert.TrustAnchor;
44
import java.security.cert.X509Certificate;
55
import java.time.LocalDateTime;
6+
import java.time.ZoneId;
67
import java.util.HashMap;
78
import java.util.HashSet;
89
import java.util.List;
@@ -115,16 +116,24 @@ public Map<String, Set<?>> getTrustAnchors(String partnerDomain) {
115116
return hashMap;
116117
}
117118

118-
119119
public String getIssuerCertId(String certIssuerDn) {
120120
LocalDateTime currentDateTime = DateUtils.getUTCCurrentDateTime();
121+
121122
List<CACertificateStore> certificates = caCertificateStoreRepository.findByCertSubject(certIssuerDn)
122123
.stream().filter(cert -> PartnerCertificateManagerUtil.isValidTimestamp(currentDateTime, cert))
123124
.collect(Collectors.toList());
124125

126+
if (certificates.size() == 0) {
127+
LocalDateTime curDateTime = LocalDateTime.now(ZoneId.systemDefault());
128+
certificates = caCertificateStoreRepository.findByCertSubject(certIssuerDn)
129+
.stream().filter(cert -> PartnerCertificateManagerUtil.isValidTimestamp(curDateTime, cert))
130+
.collect(Collectors.toList());
131+
}
132+
125133
if (certificates.size() == 1) {
126134
return certificates.get(0).getCertId();
127135
}
136+
128137
List<CACertificateStore> sortedCerts = certificates.stream()
129138
.sorted((cert1, cert2) -> cert1.getCertNotBefore().compareTo(cert2.getCertNotBefore()))
130139
.collect(Collectors.toList());

kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/partnercertservice/service/impl/PartnerCertificateManagerServiceImpl.java

Lines changed: 101 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,10 @@
44
import java.security.NoSuchAlgorithmException;
55
import java.security.PrivateKey;
66
import java.security.PublicKey;
7-
import java.security.cert.CertPathBuilder;
8-
import java.security.cert.CertPathBuilderException;
9-
import java.security.cert.CertStore;
10-
import java.security.cert.CollectionCertStoreParameters;
11-
import java.security.cert.PKIXBuilderParameters;
12-
import java.security.cert.TrustAnchor;
13-
import java.security.cert.X509CertSelector;
14-
import java.security.cert.X509Certificate;
7+
import java.security.cert.*;
158
import java.time.LocalDateTime;
169
import java.time.temporal.ChronoUnit;
17-
import java.util.Map;
18-
import java.util.Objects;
19-
import java.util.Optional;
20-
import java.util.Set;
21-
import java.util.UUID;
10+
import java.util.*;
2211
import java.util.stream.Stream;
2312
import java.util.concurrent.TimeUnit;
2413

@@ -90,6 +79,9 @@ public class PartnerCertificateManagerServiceImpl implements PartnerCertificateM
9079

9180
@Value("${mosip.kernel.partner.issuer.certificate.allowed.grace.duration:30}")
9281
private int gracePeriod;
82+
83+
@Value("${mosip.kernel.partner.resign.ftm.domain.certs:false}")
84+
private boolean resignFTMDomainCerts;
9385

9486
/**
9587
* Utility to generate Metadata
@@ -254,6 +246,45 @@ private boolean validateCertificatePath(X509Certificate reqX509Cert, String part
254246
return false;
255247
}
256248

249+
private List<? extends Certificate> getCertificateTrustPath(X509Certificate reqX509Cert, String partnerDomain) {
250+
251+
try {
252+
Map<String, Set<?>> trustStoreMap = (Map<String, Set<?>>) caCertTrustStore.get(partnerDomain); //certDBHelper.getTrustAnchors(partnerDomain);
253+
Set<TrustAnchor> rootTrustAnchors = (Set<TrustAnchor>) trustStoreMap
254+
.get(PartnerCertManagerConstants.TRUST_ROOT);
255+
Set<X509Certificate> interCerts = (Set<X509Certificate>) trustStoreMap
256+
.get(PartnerCertManagerConstants.TRUST_INTER);
257+
258+
X509CertSelector certToVerify = new X509CertSelector();
259+
certToVerify.setCertificate(reqX509Cert);
260+
261+
PKIXBuilderParameters pkixBuilderParams = new PKIXBuilderParameters(rootTrustAnchors, certToVerify);
262+
pkixBuilderParams.setRevocationEnabled(false);
263+
264+
CertStore interCertStore = CertStore.getInstance("Collection",
265+
new CollectionCertStoreParameters(interCerts));
266+
pkixBuilderParams.addCertStore(interCertStore);
267+
268+
// Building the cert path and verifying the certification chain
269+
CertPathBuilder certPathBuilder = CertPathBuilder.getInstance("PKIX");
270+
//certPathBuilder.build(pkixBuilderParams);
271+
PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) certPathBuilder.build(pkixBuilderParams);
272+
X509Certificate rootCert = result.getTrustAnchor().getTrustedCert();
273+
List<? extends Certificate> certList = result.getCertPath().getCertificates();
274+
List<Certificate> trustCertList = new ArrayList<>();
275+
certList.stream().forEach(cert -> {
276+
trustCertList.add(cert);
277+
});
278+
trustCertList.add(rootCert);
279+
return trustCertList;
280+
} catch (CertPathBuilderException | InvalidAlgorithmParameterException | NoSuchAlgorithmException exp) {
281+
LOGGER.info(PartnerCertManagerConstants.SESSIONID, PartnerCertManagerConstants.UPLOAD_CA_CERT,
282+
PartnerCertManagerConstants.EMPTY,
283+
"Ignore this exception, the exception thrown when trust validation failed.");
284+
}
285+
return null;
286+
}
287+
257288
@Override
258289
public PartnerCertificateResponseDto uploadPartnerCertificate(PartnerCertificateRequestDto partnerCertRequesteDto) {
259290

@@ -290,6 +321,63 @@ public PartnerCertificateResponseDto uploadPartnerCertificate(PartnerCertificate
290321
return responseDto;
291322
}
292323

324+
@Override
325+
public PartnerCertificateResponseDto uploadPartnerCertificateV2(PartnerCertificateRequestDto partnerCertRequesteDto) {
326+
327+
String certificateData = partnerCertRequesteDto.getCertificateData();
328+
if (!keymanagerUtil.isValidCertificateData(certificateData)) {
329+
LOGGER.error(PartnerCertManagerConstants.SESSIONID, PartnerCertManagerConstants.UPLOAD_PARTNER_CERT,
330+
PartnerCertManagerConstants.EMPTY,
331+
"Invalid Certificate Data provided to upload the partner certificate.");
332+
throw new PartnerCertManagerException(PartnerCertManagerErrorConstants.INVALID_CERTIFICATE.getErrorCode(),
333+
PartnerCertManagerErrorConstants.INVALID_CERTIFICATE.getErrorMessage());
334+
}
335+
X509Certificate reqX509Cert = (X509Certificate) keymanagerUtil.convertToCertificate(certificateData);
336+
String certThumbprint = PartnerCertificateManagerUtil.getCertificateThumbprint(reqX509Cert);
337+
String reqOrgName = partnerCertRequesteDto.getOrganizationName();
338+
String partnerDomain = validateAllowedDomains(partnerCertRequesteDto.getPartnerDomain());
339+
340+
validateBasicPartnerCertParams(reqX509Cert, certThumbprint, reqOrgName, partnerDomain);
341+
342+
List<? extends Certificate>certList = getCertificateTrustPath(reqX509Cert, partnerDomain);
343+
if (Objects.isNull(certList)) {
344+
LOGGER.error(PartnerCertManagerConstants.SESSIONID, PartnerCertManagerConstants.UPLOAD_PARTNER_CERT,
345+
PartnerCertManagerConstants.EMPTY,
346+
"Partner Certificate not allowed to upload as root CA/Intermediate CAs are not found in trust cert path.");
347+
throw new PartnerCertManagerException(
348+
PartnerCertManagerErrorConstants.ROOT_INTER_CA_NOT_FOUND.getErrorCode(),
349+
PartnerCertManagerErrorConstants.ROOT_INTER_CA_NOT_FOUND.getErrorMessage());
350+
}
351+
352+
String certSubject = PartnerCertificateManagerUtil
353+
.formatCertificateDN(reqX509Cert.getSubjectX500Principal().getName());
354+
String certIssuer = PartnerCertificateManagerUtil
355+
.formatCertificateDN(reqX509Cert.getIssuerX500Principal().getName());
356+
String issuerId = certDBHelper.getIssuerCertId(certIssuer);
357+
String certId = UUID.randomUUID().toString();
358+
359+
X509Certificate rootCert = (X509Certificate) keymanagerUtil.convertToCertificate(
360+
keymanagerService.getCertificate(PartnerCertManagerConstants.ROOT_APP_ID,
361+
Optional.of(PartnerCertManagerConstants.EMPTY)).getCertificate());
362+
String timestamp = DateUtils.getUTCCurrentDateTimeString();
363+
SignatureCertificate certificateResponse = keymanagerService.getSignatureCertificate(masterSignKeyAppId,
364+
Optional.of(PartnerCertManagerConstants.EMPTY), timestamp);
365+
X509Certificate pmsCert = certificateResponse.getCertificateEntry().getChain()[0];
366+
367+
X509Certificate resignedCert = reSignPartnerKey(reqX509Cert);
368+
String signedCertData = keymanagerUtil.getPEMFormatedData(resignedCert);
369+
certDBHelper.storePartnerCertificate(certId, certSubject, certIssuer, issuerId, reqX509Cert, certThumbprint,
370+
reqOrgName, partnerDomain, signedCertData);
371+
372+
String p7bCertChain = PartnerCertificateManagerUtil.buildP7BCertificateChain(certList, resignedCert,
373+
partnerDomain, resignFTMDomainCerts, rootCert, pmsCert);
374+
PartnerCertificateResponseDto responseDto = new PartnerCertificateResponseDto();
375+
responseDto.setCertificateId(certId);
376+
responseDto.setSignedCertificateData(p7bCertChain);
377+
responseDto.setTimestamp(DateUtils.getUTCCurrentDateTime());
378+
return responseDto;
379+
}
380+
293381
private void validateBasicPartnerCertParams(X509Certificate reqX509Cert, String certThumbprint, String reqOrgName,
294382
String partnerDomain) {
295383
boolean certExist = certDBHelper.isPartnerCertificateExist(certThumbprint, partnerDomain);

kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/partnercertservice/service/spi/PartnerCertificateManagerService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ public interface PartnerCertificateManagerService {
3535
*/
3636
public PartnerCertificateResponseDto uploadPartnerCertificate(PartnerCertificateRequestDto partnerCertResponseDto);
3737

38+
/**
39+
* Function to Upload Partner certificates
40+
*
41+
* @param PartnerCertificateRequestDto partnerCertResponseDto
42+
* @return {@link PartnerCertificateResponseDto} instance
43+
*/
44+
public PartnerCertificateResponseDto uploadPartnerCertificateV2(PartnerCertificateRequestDto partnerCertResponseDto);
45+
3846
/**
3947
* Function to Download Partner certificates
4048
*

kernel/kernel-keymanager-service/src/main/java/io/mosip/kernel/partnercertservice/util/PartnerCertificateManagerUtil.java

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
package io.mosip.kernel.partnercertservice.util;
22

3+
import java.io.IOException;
34
import java.security.InvalidKeyException;
45
import java.security.NoSuchAlgorithmException;
56
import java.security.NoSuchProviderException;
67
import java.security.SignatureException;
7-
import java.security.cert.CertificateEncodingException;
8-
import java.security.cert.CertificateException;
9-
import java.security.cert.CertificateExpiredException;
10-
import java.security.cert.CertificateNotYetValidException;
11-
import java.security.cert.X509Certificate;
8+
import java.security.cert.*;
129
import java.time.LocalDateTime;
1310
import java.time.ZoneId;
1411
import java.time.temporal.ChronoUnit;
12+
import java.util.ArrayList;
13+
import java.util.Arrays;
1514
import java.util.Date;
15+
import java.util.List;
1616

1717
import javax.security.auth.x500.X500Principal;
1818

19+
import io.mosip.kernel.core.util.CryptoUtil;
1920
import org.apache.commons.codec.digest.DigestUtils;
2021
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
2122
import org.bouncycastle.asn1.x500.RDN;
@@ -31,6 +32,8 @@
3132
import io.mosip.kernel.partnercertservice.constant.PartnerCertManagerConstants;
3233
import io.mosip.kernel.partnercertservice.constant.PartnerCertManagerErrorConstants;
3334
import io.mosip.kernel.partnercertservice.exception.PartnerCertManagerException;
35+
import org.bouncycastle.cert.jcajce.JcaCertStore;
36+
import org.bouncycastle.cms.*;
3437

3538
/**
3639
* Utility class for Partner Certificate Management
@@ -195,4 +198,36 @@ private static String getAttributeValueIfExist(X500Name x500Name, ASN1ObjectIden
195198
}
196199
return IETFUtils.valueToString((rdns[0]).getFirst().getValue());
197200
}
201+
202+
public static String buildP7BCertificateChain(List<? extends Certificate> certList, X509Certificate resignedCert,
203+
String partnerDomain, boolean resignFTMDomainCerts, X509Certificate rootCert, X509Certificate pmsCert) {
204+
205+
if (partnerDomain.toUpperCase().equals(PartnerCertManagerConstants.FTM_PARTNER_DOMAIN) && !resignFTMDomainCerts) {
206+
return buildCertChain(certList.toArray(new Certificate[0]));
207+
}
208+
209+
List<Certificate> chain = new ArrayList<>();
210+
chain.add(resignedCert);
211+
chain.add(pmsCert);
212+
chain.add(rootCert);
213+
return buildCertChain(chain.toArray(new Certificate[0]));
214+
}
215+
216+
private static String buildCertChain(Certificate[] chain) {
217+
try {
218+
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
219+
JcaCertStore jcaStore = new JcaCertStore(Arrays.asList(chain));
220+
generator.addCertificates(jcaStore);
221+
222+
CMSTypedData cmsTypedData = new CMSAbsentContent();
223+
CMSSignedData cmsSignedData = generator.generate(cmsTypedData);
224+
return CryptoUtil.encodeBase64(cmsSignedData.getEncoded());
225+
} catch (CertificateEncodingException | CMSException | IOException e) {
226+
LOGGER.error(PartnerCertManagerConstants.SESSIONID, PartnerCertManagerConstants.UPLOAD_PARTNER_CERT,
227+
PartnerCertManagerConstants.PCM_UTIL, "Error generating p7b certificates chain.");
228+
throw new PartnerCertManagerException(PartnerCertManagerErrorConstants.CERTIFICATE_THUMBPRINT_ERROR.getErrorCode(),
229+
PartnerCertManagerErrorConstants.CERTIFICATE_THUMBPRINT_ERROR.getErrorMessage(), e);
230+
}
231+
}
232+
198233
}

0 commit comments

Comments
 (0)