Add tenant based storing and loading SCEP certificates

remotes/1725563413541109883/master
Pahansith Gunathilake 2 years ago committed by pasindu
parent a603a69f3e
commit 84563078d3

@ -51,6 +51,16 @@ public interface CertificateDAO {
*/ */
CertificateResponse retrieveCertificate(String serialNumber) throws CertificateManagementDAOException; CertificateResponse retrieveCertificate(String serialNumber) throws CertificateManagementDAOException;
/**
* Obtain a certificated stored in the database by providing the common name and the tenant ID
*
* @param serialNumber Serial number (Common name) of the certificate
* @param tenantId ID of the certificate owning tenant
* @return representation of the certificate.
* @throws CertificateManagementDAOException if fails to read the certificate from the database
*/
CertificateResponse retrieveCertificate(String serialNumber, int tenantId) throws CertificateManagementDAOException;
/** /**
* Get all the certificates in a paginated manner. * Get all the certificates in a paginated manner.
* *

@ -119,6 +119,42 @@ public abstract class AbstractCertificateDAOImpl implements CertificateDAO{
return certificateResponse; return certificateResponse;
} }
@Override
public CertificateResponse retrieveCertificate(String serialNumber, int tenantId) throws CertificateManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
CertificateResponse certificateResponse = null;
try {
conn = this.getConnection();
String query =
"SELECT CERTIFICATE, SERIAL_NUMBER, TENANT_ID, USERNAME FROM"
+ " DM_DEVICE_CERTIFICATE WHERE SERIAL_NUMBER = ? AND TENANT_ID = ? ";
stmt = conn.prepareStatement(query);
stmt.setString(1, serialNumber);
stmt.setInt(2, tenantId);
resultSet = stmt.executeQuery();
if (resultSet.next()) {
certificateResponse = new CertificateResponse();
byte[] certificateBytes = resultSet.getBytes("CERTIFICATE");
certificateResponse.setCertificate(certificateBytes);
certificateResponse.setSerialNumber(resultSet.getString("SERIAL_NUMBER"));
certificateResponse.setTenantId(resultSet.getInt("TENANT_ID"));
certificateResponse.setUsername(resultSet.getString("USERNAME"));
CertificateGenerator.extractCertificateDetails(certificateBytes, certificateResponse);
}
} catch (SQLException e) {
String errorMsg =
"Unable to get the read the certificate with serial" + serialNumber;
log.error(errorMsg, e);
throw new CertificateManagementDAOException(errorMsg, e);
} finally {
CertificateManagementDAOUtil.cleanupResources(stmt, resultSet);
}
return certificateResponse;
}
@Override @Override
public List<CertificateResponse> searchCertificate(String serialNumber) public List<CertificateResponse> searchCertificate(String serialNumber)
throws CertificateManagementDAOException { throws CertificateManagementDAOException {

@ -376,15 +376,31 @@ public class CertificateGenerator {
CertificateResponse lookUpCertificate = null; CertificateResponse lookUpCertificate = null;
KeyStoreReader keyStoreReader = new KeyStoreReader(); KeyStoreReader keyStoreReader = new KeyStoreReader();
if (distinguishedName != null && !distinguishedName.isEmpty()) { if (distinguishedName != null && !distinguishedName.isEmpty()) {
if (distinguishedName.contains("/CN=")) { if (distinguishedName.contains("CN=")) {
String[] dnSplits = distinguishedName.split("/"); String[] dnSplits = null;
if (distinguishedName.contains("/")) {
dnSplits = distinguishedName.split("/");
} else if (distinguishedName.contains(",")) {
//some older versions of nginx will forward the client certificate subject dn separated with commas
dnSplits = distinguishedName.split(",");
}
String commonNameExtracted = null;
int tenantId = 0;
if (dnSplits != null && dnSplits.length >= 1) {
for (String dnPart : dnSplits) { for (String dnPart : dnSplits) {
if (dnPart.contains("CN=")) { if (dnPart.contains("CN=")) {
String commonNameExtracted = dnPart.replace("CN=", ""); commonNameExtracted = dnPart.replace("CN=", "");
lookUpCertificate = keyStoreReader.getCertificateBySerial(commonNameExtracted); } else if (dnPart.contains("OU=")) {
break; //the OU of the certificate will be like OU=tenant_<TENANT_ID> ex: OU=tenant_-1234
//splitting by underscore to extract the tenant domain
String[] orgUnitSplits = dnPart.split("_");
tenantId = Integer.parseInt(orgUnitSplits[1]);
}
} }
} }
lookUpCertificate = keyStoreReader.getCertificateBySerial(commonNameExtracted, tenantId);
} else { } else {
LdapName ldapName; LdapName ldapName;
try { try {
@ -813,10 +829,6 @@ public class CertificateGenerator {
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
<<<<<<< HEAD:components/certificate-mgt/io.entgra.device.mgt.core.certificate.mgt.core/src/main/java/io/entgra/device/mgt/core/certificate/mgt/core/impl/CertificateGenerator.java
<<<<<<< HEAD:components/certificate-mgt/io.entgra.device.mgt.core.certificate.mgt.core/src/main/java/io/entgra/device/mgt/core/certificate/mgt/core/impl/CertificateGenerator.java
=======
>>>>>>> d34adaae96 (Fix issue with Nginx not recognizing the SCEP client certificate (#105)):components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/main/java/org/wso2/carbon/certificate/mgt/core/impl/CertificateGenerator.java
//Reversing the order of components of the subject DN due to Nginx not verifying the client certificate //Reversing the order of components of the subject DN due to Nginx not verifying the client certificate
//generated by Java using this subject DN. //generated by Java using this subject DN.
//Ref: https://stackoverflow.com/questions/33769978 & engineering mail SCEP implementation for Android //Ref: https://stackoverflow.com/questions/33769978 & engineering mail SCEP implementation for Android
@ -829,8 +841,9 @@ public class CertificateGenerator {
X500Name issuerName = new X500Name(subjectDn); X500Name issuerName = new X500Name(subjectDn);
String commonName = certificationRequest.getSubject().getRDNs(BCStyle.CN)[0].getFirst() String commonName = certificationRequest.getSubject().getRDNs(BCStyle.CN)[0].getFirst()
.getValue().toString(); .getValue().toString();
X500Name subjectName = new X500Name("O=" + commonName + "O=AndroidDevice,CN=" + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
serialNumber); X500Name subjectName = new X500Name("O=" + commonName + ",CN=" +
serialNumber + ", OU=tenant_"+tenantId);
Date startDate = new Date(System.currentTimeMillis()); Date startDate = new Date(System.currentTimeMillis());
Date endDate = new Date(System.currentTimeMillis() Date endDate = new Date(System.currentTimeMillis()
+ TimeUnit.DAYS.toMillis(365 * 100)); + TimeUnit.DAYS.toMillis(365 * 100));

@ -271,6 +271,43 @@ public class KeyStoreReader {
return raPrivateKey; return raPrivateKey;
} }
public CertificateResponse getCertificateBySerial(String serialNumber, int tenantId) throws KeystoreException {
CertificateResponse certificateResponse = null;
try {
CertificateCacheManager cacheManager = CertificateCacheManagerImpl.getInstance();
certificateResponse = cacheManager.getCertificateBySerial(serialNumber);
if (certificateResponse == null) {
try {
CertificateManagementDAOFactory.openConnection();
certificateResponse = certDao.retrieveCertificate(serialNumber, tenantId);
} catch (SQLException e) {
String errorMsg = "Error when making a connection to the database.";
throw new KeystoreException(errorMsg, e);
} finally {
CertificateManagementDAOFactory.closeConnection();
}
if (certificateResponse != null && certificateResponse.getCertificate() != null) {
Certificate certificate = (Certificate) Serializer.deserialize(certificateResponse.getCertificate());
if (certificate instanceof X509Certificate) {
X509Certificate x509cert = (X509Certificate) certificate;
String commonName = CertificateGenerator.getCommonName(x509cert);
certificateResponse.setCommonName(commonName);
cacheManager.addCertificateBySerial(serialNumber, certificateResponse);
}
}
}
} catch (CertificateManagementDAOException e) {
String errorMsg = "Error when retrieving certificate from the the database for the serial number: " +
serialNumber;
throw new KeystoreException(errorMsg, e);
} catch (ClassNotFoundException | IOException e) {
String errorMsg = "Error when de-serializing saved certificate.";
throw new KeystoreException(errorMsg, e);
}
return certificateResponse;
}
public CertificateResponse getCertificateBySerial(String serialNumber) throws KeystoreException { public CertificateResponse getCertificateBySerial(String serialNumber) throws KeystoreException {
CertificateResponse certificateResponse = null; CertificateResponse certificateResponse = null;
try { try {

@ -0,0 +1,32 @@
/* Copyright (c) 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.common.exception;
/**
* Represents the exception thrown during storing and retrieving the artifacts.
*/
public class StorageManagementException extends Exception {
public StorageManagementException(String message, Throwable ex) {
super(message, ex);
}
public StorageManagementException(String message) {
super(message);
}
}
Loading…
Cancel
Save