From 8a2cbb2c7fee6fb9cb2d3f39345288fb993c2b8d Mon Sep 17 00:00:00 2001
From: Ashan Thamara Palihakkara
<75057725+ashanthamara@users.noreply.github.com>
Date: Sun, 3 Nov 2024 11:04:14 +0530
Subject: [PATCH] Refactor application-mgt component to utilize certificate-mgt
component for certificate management (#6087)
* Add certificate-mgt dependency to application-mgt component
* Refactor application-mgt to untilize certificate-mgt component for application certificate management
* Add sonarcloud suggestions
* Remove unused imports
* Add unit tests for application certificate management
* Modify unit tests
* Refactor application-certificate unit tests
* Improve line coverage
* Add sonarCloud suggestion to reduce method complexity
* Change CERTIFICATE property name to the defined constant variable
* address comments
* Remove schema change
* Add comments to the test methods
* Improve assertions
* Minor improvement
---
.../pom.xml | 7 +
.../mgt/ApplicationManagementServiceImpl.java | 13 -
.../mgt/dao/impl/ApplicationDAOImpl.java | 423 ++++++++----------
.../mgt/dao/impl/ApplicationMgtDBQueries.java | 28 ++
...ApplicationManagementServiceComponent.java | 23 +
...ationManagementServiceComponentHolder.java | 22 +
.../ApplicationManagementServiceImplTest.java | 319 +++++++++++++
7 files changed, 581 insertions(+), 254 deletions(-)
diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml b/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml
index 3cfed6bb713d..cb58488e74a9 100644
--- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml
+++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/pom.xml
@@ -191,6 +191,10 @@
org.wso2.carbon.identity.framework
org.wso2.carbon.identity.secret.mgt.core
+
+ org.wso2.carbon.identity.framework
+ org.wso2.carbon.identity.certificate.management
+
@@ -260,6 +264,9 @@
version="${org.wso2.carbon.identity.organization.management.core.version.range}",
org.wso2.carbon.identity.api.resource.mgt.model; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.api.resource.mgt.util; version="${carbon.identity.package.import.version.range}",
+ org.wso2.carbon.identity.certificate.management.service; version="${carbon.identity.package.import.version.range}",
+ org.wso2.carbon.identity.certificate.management.exception; version="${carbon.identity.package.import.version.range}",
+ org.wso2.carbon.identity.certificate.management.model; version="${carbon.identity.package.import.version.range}",
!org.wso2.carbon.identity.application.mgt.internal,
diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/ApplicationManagementServiceImpl.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/ApplicationManagementServiceImpl.java
index a9e845f64e23..15cfd3acc428 100644
--- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/ApplicationManagementServiceImpl.java
+++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/ApplicationManagementServiceImpl.java
@@ -173,7 +173,6 @@
import static org.wso2.carbon.identity.application.mgt.inbound.InboundFunctions.updateOrInsertInbound;
import static org.wso2.carbon.identity.central.log.mgt.utils.LoggerUtils.triggerAuditLogEvent;
import static org.wso2.carbon.identity.core.util.IdentityUtil.getInitiatorId;
-import static org.wso2.carbon.identity.core.util.IdentityUtil.isValidPEMCertificate;
import static org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants.Error.ROLE_MANAGEMENT_ERROR_CODE_PREFIX;
import static org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants.Error.ROLE_NOT_FOUND;
import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
@@ -3036,7 +3035,6 @@ private void doPreUpdateChecks(String storedAppName, ServiceProvider updatedApp,
validateAuthorization(updatedAppName, storedAppName, username, tenantDomain);
validateAppName(storedAppName, updatedApp, tenantDomain);
- validateApplicationCertificate(updatedApp, tenantDomain);
boolean isValid = isAssociatedRolesConfigValid(updatedApp, tenantDomain);
if (!isValid) {
throw new IdentityApplicationManagementClientException(
@@ -3058,17 +3056,6 @@ private void updateApplicationPermissions(ServiceProvider updatedApp, String upd
}
}
- private void validateApplicationCertificate(ServiceProvider updatedApp,
- String tenantDomain) throws IdentityApplicationManagementException {
-
- if (!isValidPEMCertificate(updatedApp.getCertificateContent())) {
- String error = "Provided application certificate for application with name: %s in tenantDomain: %s " +
- "is malformed.";
- throw buildClientException(INVALID_REQUEST,
- String.format(error, updatedApp.getApplicationName(), tenantDomain));
- }
- }
-
private void validateApplicationConfigurations(ServiceProvider application,
String tenantDomain,
String username) throws IdentityApplicationManagementException {
diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationDAOImpl.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationDAOImpl.java
index 063bb4bd6a96..8579289fd2f3 100644
--- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationDAOImpl.java
+++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationDAOImpl.java
@@ -80,6 +80,9 @@
import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.DefinedByType;
import org.wso2.carbon.identity.base.IdentityException;
import org.wso2.carbon.identity.base.IdentityRuntimeException;
+import org.wso2.carbon.identity.certificate.management.exception.CertificateMgtClientException;
+import org.wso2.carbon.identity.certificate.management.exception.CertificateMgtException;
+import org.wso2.carbon.identity.certificate.management.model.Certificate;
import org.wso2.carbon.identity.core.CertificateRetrievingException;
import org.wso2.carbon.identity.core.URLBuilderException;
import org.wso2.carbon.identity.core.model.ExpressionNode;
@@ -105,11 +108,9 @@
import org.wso2.carbon.utils.DBUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
-import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -126,9 +127,11 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import java.util.stream.Stream;
import static java.util.Objects.isNull;
@@ -150,6 +153,7 @@
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Error.INVALID_FILTER;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Error.INVALID_LIMIT;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Error.INVALID_OFFSET;
+import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Error.INVALID_REQUEST;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.Error.SORTING_NOT_IMPLEMENTED;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.ISSUER_SP_PROPERTY_NAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.IS_API_BASED_AUTHENTICATION_ENABLED_DISPLAY_NAME;
@@ -367,7 +371,7 @@ public int createApplication(ServiceProvider application, String tenantDomain)
IdentityDatabaseUtil.commitTransaction(connection);
return result.getApplicationId();
} catch (SQLException e) {
- IdentityDatabaseUtil.rollbackTransaction(connection);
+ rollbackAddApplicationTransaction(connection, application, tenantDomain);
if (isApplicationConflict(e)) {
throw new IdentityApplicationManagementClientException(APPLICATION_ALREADY_EXISTS.getCode(),
"Application already exists with name: " + application.getApplicationName()
@@ -569,6 +573,9 @@ public void updateApplication(ServiceProvider serviceProvider, String tenantDoma
addApplicationConfigurations(connection, serviceProvider, tenantDomain);
IdentityDatabaseUtil.commitTransaction(connection);
+ } catch (IdentityApplicationManagementClientException e) {
+ IdentityDatabaseUtil.rollbackTransaction(connection);
+ throw e;
} catch (SQLException | UserStoreException | IdentityApplicationManagementException e) {
IdentityDatabaseUtil.rollbackTransaction(connection);
throw new IdentityApplicationManagementException("Failed to update application id: " + applicationId, e);
@@ -594,7 +601,7 @@ private void addApplicationConfigurations(Connection connection, ServiceProvider
// you can change application name, description, isSasApp...
updateBasicApplicationData(serviceProvider, connection);
- updateApplicationCertificate(serviceProvider, tenantID, connection);
+ updateApplicationCertificate(serviceProvider, tenantID);
updateInboundProvisioningConfiguration(applicationId, serviceProvider.getInboundProvisioningConfig(),
connection);
@@ -754,85 +761,101 @@ private void updateConsentPurposeConfiguration(Connection connection, int applic
}
/**
- * Updates the application certificate record in the database, with the certificate in the given service provider
- * object. If the certificate content is available in the given service provider and a reference is not available,
- * create a new database record for the certificate and add the reference to the given service provider object.
+ * Updates the application certificate record in the database using ApplicationCertificateMgtService,
+ * with the certificate in the given service provider object. If the certificate content is available in the given
+ * service provider and a reference is not available, create a new database record for the certificate and add the
+ * reference to the given service provider object.
*
- * @param serviceProvider
- * @param tenantID
- * @param connection
- * @throws SQLException
+ * @param serviceProvider Service provider object.
+ * @param tenantID Tenant ID.
+ * @throws IdentityApplicationManagementException If an error occurs while updating the certificate.
*/
- private void updateApplicationCertificate(ServiceProvider serviceProvider, int tenantID,
- Connection connection)
- throws SQLException, IdentityApplicationManagementException {
+ private void updateApplicationCertificate(ServiceProvider serviceProvider, int tenantID)
+ throws IdentityApplicationManagementException {
- // If the certificate content is empty, remove the certificate reference property if exists.
- // And remove the certificate.
if (StringUtils.isBlank(serviceProvider.getCertificateContent())) {
+ // Remove the certificate reference property if exists and remove the certificate.
+ removeCertificateReferenceAndDelete(serviceProvider, tenantID);
+ } else {
+ String certificateReferenceIdString = getCertificateReferenceID(serviceProvider.getSpProperties());
+ if (certificateReferenceIdString != null) {
+ // If there is a reference, update the relevant existing certificate record.
+ updateCertificate(certificateReferenceIdString, serviceProvider.getCertificateContent(), tenantID);
+ } else {
+ // There is no existing reference. Persisting the certificate as a new record.
+ persistApplicationCertificate(serviceProvider, tenantID);
+ }
+ }
+ }
- ServiceProviderProperty[] serviceProviderProperties = serviceProvider.getSpProperties();
+ /**
+ * Removes the certificate reference property from the given service provider object and deletes the certificate
+ * record from the database.
+ *
+ * @param serviceProvider Service provider object.
+ * @param tenantID Tenant ID.
+ * @throws IdentityApplicationManagementException If an error occurs while removing the certificate reference.
+ */
+ private void removeCertificateReferenceAndDelete(ServiceProvider serviceProvider, int tenantID)
+ throws IdentityApplicationManagementException {
- if (serviceProviderProperties != null) {
+ ServiceProviderProperty[] spProperties = serviceProvider.getSpProperties();
- // Get the index of the certificate reference property index in the properties array.
- int certificateReferenceIdIndex = -1;
- String certificateReferenceId = null;
- for (int i = 0; i < serviceProviderProperties.length; i++) {
- if ("CERTIFICATE".equals(serviceProviderProperties[i].getName())) {
- certificateReferenceIdIndex = i;
- certificateReferenceId = serviceProviderProperties[i].getValue();
- break;
- }
- }
+ if (spProperties == null) {
+ return;
+ }
- // If there is a certificate reference, remove it from the properties array.
- // Removing will be done by creating a new array and copying the elements other than the
- // certificate reference from the existing array,
- if (certificateReferenceIdIndex > -1) {
+ OptionalInt certificateReferenceIdIndex = IntStream.range(0, spProperties.length)
+ .filter(index -> SP_PROPERTY_NAME_CERTIFICATE.equals(spProperties[index].getName()))
+ .findFirst();
- ServiceProviderProperty[] propertiesWithoutCertificateReference =
- new ServiceProviderProperty[serviceProviderProperties.length - 1];
+ if (certificateReferenceIdIndex.isPresent()) {
+ int certificateReferenceIndex = certificateReferenceIdIndex.getAsInt();
+ int certificateID = Integer.parseInt(spProperties[certificateReferenceIndex].getValue());
- System.arraycopy(serviceProviderProperties, 0, propertiesWithoutCertificateReference,
- 0, certificateReferenceIdIndex);
- System.arraycopy(serviceProviderProperties, certificateReferenceIdIndex + 1,
- propertiesWithoutCertificateReference, certificateReferenceIdIndex,
- propertiesWithoutCertificateReference.length - certificateReferenceIdIndex);
+ serviceProvider.setSpProperties(getFilteredSpProperties(spProperties, certificateReferenceIndex));
+ deleteCertificate(certificateID, IdentityTenantUtil.getTenantDomain(tenantID));
+ }
+ }
- serviceProvider.setSpProperties(propertiesWithoutCertificateReference);
- deleteCertificate(connection, Integer.parseInt(certificateReferenceId));
- }
- }
- } else {
- // First get the certificate reference from the application properties.
- ServiceProviderProperty[] serviceProviderProperties = serviceProvider.getSpProperties();
+ /**
+ * Returns a new array of service provider properties with the property at the specified index removed.
+ * This method creates a copy of the original `spProperties` array, omitting the element at `indexToRemove`.
+ *
+ * @param spProperties An array of service provider properties.
+ * @param indexToRemove The index of the property to be removed from the array.
+ * @return A new array of service provider properties, excluding the property at the specified index.
+ */
+ private ServiceProviderProperty[] getFilteredSpProperties(ServiceProviderProperty[] spProperties,
+ int indexToRemove) {
- String certificateReferenceIdString = getCertificateReferenceID(serviceProviderProperties);
+ ServiceProviderProperty[] updatedSpProperties = new ServiceProviderProperty[spProperties.length - 1];
+ System.arraycopy(spProperties, 0, updatedSpProperties, 0, indexToRemove);
+ System.arraycopy(spProperties, indexToRemove + 1, updatedSpProperties, indexToRemove,
+ updatedSpProperties.length - indexToRemove);
- // If there is a reference, update the relevant certificate record.
- if (certificateReferenceIdString != null) { // Update the existing record.
- PreparedStatement statementToUpdateCertificate = null;
- try {
- statementToUpdateCertificate = connection.prepareStatement(
- ApplicationMgtDBQueries.UPDATE_CERTIFICATE);
- setBlobValue(serviceProvider.getCertificateContent(), statementToUpdateCertificate, 1);
- statementToUpdateCertificate.setInt(2, Integer.parseInt(certificateReferenceIdString));
-
- statementToUpdateCertificate.executeUpdate();
- } catch (IOException e) {
- throw new IdentityApplicationManagementException("An error occurred while processing content " +
- "stream of certificate.", e);
- } finally {
- IdentityApplicationManagementUtil.closeStatement(statementToUpdateCertificate);
- }
- } else {
- /*
- There is no existing reference.
- Persisting the certificate in the given service provider as a new record.
- */
- persistApplicationCertificate(serviceProvider, tenantID, connection);
- }
+ return updatedSpProperties;
+ }
+
+ /**
+ * Update the existing certificate record with the given certificate ID.
+ *
+ * @param certificateId Certificate ID.
+ * @param certificateContent Certificate content to be updated.
+ * @param tenantID Tenant ID.
+ * @throws IdentityApplicationManagementException If an error occurs while updating the certificate.
+ */
+ private void updateCertificate(String certificateId, String certificateContent, int tenantID)
+ throws IdentityApplicationManagementException {
+
+ try {
+ ApplicationManagementServiceComponentHolder.getInstance().getApplicationCertificateMgtService()
+ .updateCertificateContent(Integer.parseInt(certificateId), certificateContent,
+ IdentityTenantUtil.getTenantDomain(tenantID));
+ } catch (CertificateMgtClientException e) {
+ throw new IdentityApplicationManagementClientException(INVALID_REQUEST.getCode(), e.getDescription(), e);
+ } catch (CertificateMgtException e) {
+ throw new IdentityApplicationManagementException("Error while updating certificate", e);
}
}
@@ -859,35 +882,21 @@ private String getCertificateReferenceID(ServiceProviderProperty[] serviceProvid
* Persists the certificate content of the given service provider object,
* and adds ID of the newly added certificate as a property of the service provider object.
*
- * @param serviceProvider
- * @param tenantID
- * @param connection
- * @throws SQLException
+ * @param serviceProvider Service provider object.
+ * @param tenantID Tenant ID.
+ * @throws IdentityApplicationManagementException If an error occurs while adding the certificate.
*/
- private void persistApplicationCertificate(ServiceProvider serviceProvider, int tenantID,
- Connection connection)
- throws SQLException, IdentityApplicationManagementException {
+ private void persistApplicationCertificate(ServiceProvider serviceProvider, int tenantID)
+ throws IdentityApplicationManagementException {
- // Configure the prepared statement to collect the auto generated id of the database record.
- PreparedStatement statementToAddCertificate = null;
- ResultSet results = null;
try {
-
- String dbProductName = connection.getMetaData().getDatabaseProductName();
- statementToAddCertificate = connection.prepareStatement(ApplicationMgtDBQueries.ADD_CERTIFICATE,
- new String[] {DBUtils.getConvertedAutoGeneratedColumnName(dbProductName, "ID")});
-
- statementToAddCertificate.setString(1, serviceProvider.getApplicationName());
- setBlobValue(serviceProvider.getCertificateContent(), statementToAddCertificate, 2);
- statementToAddCertificate.setInt(3, tenantID);
- statementToAddCertificate.execute();
-
- results = statementToAddCertificate.getGeneratedKeys();
-
- int newlyAddedCertificateID = 0;
- if (results.next()) {
- newlyAddedCertificateID = results.getInt(1);
- }
+ Certificate certificate = new Certificate.Builder()
+ .name(serviceProvider.getApplicationName())
+ .certificateContent(serviceProvider.getCertificateContent())
+ .build();
+ int newlyAddedCertificateID = ApplicationManagementServiceComponentHolder.getInstance()
+ .getApplicationCertificateMgtService().addCertificate(certificate,
+ IdentityTenantUtil.getTenantDomain(tenantID));
// Not all JDBC drivers support getting the auto generated database ID.
// So if the ID is not returned, get the ID by querying the database passing the certificate name.
@@ -895,16 +904,14 @@ private void persistApplicationCertificate(ServiceProvider serviceProvider, int
if (log.isDebugEnabled()) {
log.debug("JDBC Driver did not return the application id, executing Select operation");
}
- newlyAddedCertificateID = getCertificateIDByName(serviceProvider.getApplicationName(),
- tenantID, connection);
+ newlyAddedCertificateID = getCertificateIDByName(serviceProvider.getApplicationName(), tenantID);
}
addApplicationCertificateReferenceAsServiceProviderProperty(serviceProvider, newlyAddedCertificateID);
- } catch (IOException e) {
- throw new IdentityApplicationManagementException("An error occurred while processing content stream " +
- "of certificate.", e);
- } finally {
- IdentityApplicationManagementUtil.closeResultSet(results);
- IdentityApplicationManagementUtil.closeStatement(statementToAddCertificate);
+ } catch (CertificateMgtClientException e) {
+ throw new IdentityApplicationManagementClientException(INVALID_REQUEST.getCode(), e.getDescription(), e);
+ } catch (CertificateMgtException e) {
+ throw new IdentityApplicationManagementServerException("Error while adding certificate for application: " +
+ serviceProvider.getApplicationName(), e);
}
}
@@ -931,8 +938,8 @@ private void addApplicationCertificateReferenceAsServiceProviderProperty(Service
}
ServiceProviderProperty propertyForCertificate = new ServiceProviderProperty();
- propertyForCertificate.setDisplayName("CERTIFICATE");
- propertyForCertificate.setName("CERTIFICATE");
+ propertyForCertificate.setDisplayName(SP_PROPERTY_NAME_CERTIFICATE);
+ propertyForCertificate.setName(SP_PROPERTY_NAME_CERTIFICATE);
propertyForCertificate.setValue(String.valueOf(newlyAddedCertificateID));
newServiceProviderProperties[newServiceProviderProperties.length - 1] = propertyForCertificate;
@@ -943,34 +950,28 @@ private void addApplicationCertificateReferenceAsServiceProviderProperty(Service
/**
* Returns the database ID of the certificate with the given certificate name and the tenant ID.
*
- * @param applicationName
- * @param tenantID
- * @param connection
- * @return
- * @throws SQLException
+ * @param applicationName Name of the application.
+ * @param tenantID Tenant ID.
+ * @return Certificate ID.
+ * @throws IdentityApplicationManagementException If an error occurs while retrieving the certificate ID.
*/
- private int getCertificateIDByName(String applicationName, int tenantID, Connection connection)
- throws SQLException {
+ private int getCertificateIDByName(String applicationName, int tenantID)
+ throws IdentityApplicationManagementException {
- PreparedStatement statementToGetCertificateId = null;
- ResultSet results = null;
try {
- statementToGetCertificateId = connection.prepareStatement(
- ApplicationMgtDBQueries.GET_CERTIFICATE_ID_BY_NAME);
- statementToGetCertificateId.setString(1, applicationName);
- statementToGetCertificateId.setInt(2, tenantID);
-
- results = statementToGetCertificateId.executeQuery();
+ Certificate certificate = ApplicationManagementServiceComponentHolder.getInstance()
+ .getApplicationCertificateMgtService().getCertificateByName(applicationName,
+ IdentityTenantUtil.getTenantDomain(tenantID));
- int applicationId = -1;
- while (results.next()) {
- applicationId = results.getInt(1);
+ int certificateId = -1;
+ if (certificate != null) {
+ certificateId = Integer.parseInt(certificate.getId());
}
- return applicationId;
- } finally {
- IdentityApplicationManagementUtil.closeResultSet(results);
- IdentityApplicationManagementUtil.closeStatement(statementToGetCertificateId);
+ return certificateId;
+ } catch (CertificateMgtException e) {
+ throw new IdentityApplicationManagementException("Error while retrieving certificate ID by name " +
+ "for application: " + applicationName, e);
}
}
@@ -1904,48 +1905,34 @@ private ConsentPurposeConfigs getConsentPurposeConfigs(Connection connection, in
* Retrieves the certificate content from the database using the certificate reference id property of a
* service provider.
*
- * @param serviceProviderProperties
- * @param connection
- * @return
- * @throws CertificateRetrievingException
+ * @param serviceProviderProperties List of service provider properties.
+ * @return Certificate content.
+ * @throws CertificateRetrievingException If an error occurs while retrieving the certificate.
*/
- private String getCertificateContent(List serviceProviderProperties, Connection connection)
+ private String getCertificateContent(List serviceProviderProperties)
throws CertificateRetrievingException {
String certificateReferenceId = null;
for (ServiceProviderProperty property : serviceProviderProperties) {
- if ("CERTIFICATE".equals(property.getName())) {
+ if (SP_PROPERTY_NAME_CERTIFICATE.equals(property.getName())) {
certificateReferenceId = property.getValue();
}
}
if (certificateReferenceId != null) {
-
- PreparedStatement statementForFetchingCertificate = null;
- ResultSet results = null;
+ Certificate certificate;
try {
- statementForFetchingCertificate = connection.prepareStatement(
- ApplicationMgtDBQueries.GET_CERTIFICATE_BY_ID);
- statementForFetchingCertificate.setInt(1, Integer.parseInt(certificateReferenceId));
-
- results = statementForFetchingCertificate.executeQuery();
-
- String certificateContent = null;
- while (results.next()) {
- certificateContent = getBlobValue(results.getBinaryStream("CERTIFICATE_IN_PEM"));
- }
+ certificate = ApplicationManagementServiceComponentHolder.getInstance()
+ .getApplicationCertificateMgtService().getCertificate(Integer.parseInt(certificateReferenceId),
+ CarbonContext.getThreadLocalCarbonContext().getTenantDomain());
- if (certificateContent != null) {
- return certificateContent;
+ if (certificate != null) {
+ return certificate.getCertificateContent();
}
- } catch (SQLException | IOException e) {
- String errorMessage = "An error occurred while retrieving the certificate for the " +
- "application.";
+ } catch (CertificateMgtException e) {
+ String errorMessage = "An error occurred while retrieving the certificate for the application.";
log.error(errorMessage);
throw new CertificateRetrievingException(errorMessage, e);
- } finally {
- IdentityApplicationManagementUtil.closeResultSet(results);
- IdentityApplicationManagementUtil.closeStatement(statementForFetchingCertificate);
}
}
return null;
@@ -2288,7 +2275,7 @@ public ServiceProvider getApplication(int applicationId) throws IdentityApplicat
serviceProvider.setRequestPathAuthenticatorConfigs(requestPathAuthenticators);
serviceProvider.setSpProperties(propertyList.toArray(new ServiceProviderProperty[0]));
- serviceProvider.setCertificateContent(getCertificateContent(propertyList, connection));
+ serviceProvider.setCertificateContent(getCertificateContent(propertyList));
// Set role associations.
serviceProvider.setAssociatedRolesConfig(
@@ -2445,7 +2432,7 @@ public ServiceProvider getApplicationWithRequiredAttributes(int applicationId, L
readAndSetConfigurationsFromProperties(propertyList,
serviceProvider.getLocalAndOutBoundAuthenticationConfig());
serviceProvider.setSpProperties(propertyList.toArray(new ServiceProviderProperty[0]));
- serviceProvider.setCertificateContent(getCertificateContent(propertyList, connection));
+ serviceProvider.setCertificateContent(getCertificateContent(propertyList));
}
if (TEMPLATE_ID_SP_PROPERTY_NAME.equals(requiredAttribute)) {
serviceProvider.setTemplateId(getTemplateId(propertyList));
@@ -4296,7 +4283,7 @@ public void deleteApplication(String appName) throws IdentityApplicationManageme
try {
// Delete the application certificate if there is any.
- deleteCertificate(connection, appName, tenantID);
+ deleteCertificate(appName, tenantID);
// First, delete all the clients of the application
int applicationID = getApplicationIDByName(appName, tenantID, connection);
@@ -4431,9 +4418,6 @@ public void deleteApplications(int tenantId) throws IdentityApplicationManagemen
try (Connection connection = IdentityDatabaseUtil.getDBConnection(true)) {
- // Delete the application certificates of the tenant.
- deleteCertificatesByTenantId(connection, tenantId);
-
try (PreparedStatement deleteClientPrepStmt = connection
.prepareStatement(ApplicationMgtDBQueries.REMOVE_APPS_FROM_APPMGT_APP_BY_TENANT_ID)) {
deleteClientPrepStmt.setInt(1, tenantId);
@@ -4664,15 +4648,14 @@ public void deletePermissionAndRoleConfiguration(int applicationID, Connection c
/**
* Delete the certificate of the given application if there is one.
*
- * @param connection
- * @param appName
- * @param tenantID
- * @throws UserStoreException
- * @throws IdentityApplicationManagementException
- * @throws SQLException
+ * @param appName Application name.
+ * @param tenantID Tenant ID.
+ * @throws UserStoreException If an error occurred while resolving tenant.
+ * @throws IdentityApplicationManagementException If an error occurred while retrieving the application or
+ * deleting the certificate.
*/
- private void deleteCertificate(Connection connection, String appName, int tenantID)
- throws UserStoreException, IdentityApplicationManagementException, SQLException {
+ private void deleteCertificate(String appName, int tenantID) throws UserStoreException,
+ IdentityApplicationManagementException {
String tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
@@ -4686,50 +4669,24 @@ private void deleteCertificate(Connection connection, String appName, int tenant
String certificateReferenceID = getCertificateReferenceID(application.getSpProperties());
if (certificateReferenceID != null) {
- deleteCertificate(connection, Integer.parseInt(certificateReferenceID));
+ deleteCertificate(Integer.parseInt(certificateReferenceID), IdentityTenantUtil.getTenantDomain(tenantID));
}
}
/**
* Deletes the certificate for given ID from the database.
*
- * @param connection
- * @param id
+ * @param id Certificate ID.
+ * @param tenantDomain Tenant domain.
+ * @throws IdentityApplicationManagementException If an error occurred while deleting the certificate.
*/
- private void deleteCertificate(Connection connection, int id) throws SQLException {
+ private void deleteCertificate(int id, String tenantDomain) throws IdentityApplicationManagementException {
- PreparedStatement statementToRemoveCertificate = null;
try {
-
- statementToRemoveCertificate = connection.prepareStatement(ApplicationMgtDBQueries.REMOVE_CERTIFICATE);
- statementToRemoveCertificate.setInt(1, id);
- statementToRemoveCertificate.execute();
- } finally {
- IdentityApplicationManagementUtil.closeStatement(statementToRemoveCertificate);
- }
- }
-
- /**
- * Deletes all certificates of a given tenant id from the database.
- *
- * @param connection The database connection.
- * @param tenantId The id of the tenant.
- */
- private void deleteCertificatesByTenantId(Connection connection, int tenantId) throws SQLException {
-
- if (log.isDebugEnabled()) {
- log.debug("Deleting all application certificates of tenant: " + tenantId);
- }
-
- PreparedStatement deleteCertificatesStmt = null;
-
- try {
- deleteCertificatesStmt = connection.prepareStatement(
- ApplicationMgtDBQueries.REMOVE_CERTIFICATES_BY_TENANT_ID);
- deleteCertificatesStmt.setInt(1, tenantId);
- deleteCertificatesStmt.execute();
- } finally {
- IdentityApplicationManagementUtil.closeStatement(deleteCertificatesStmt);
+ ApplicationManagementServiceComponentHolder.getInstance().getApplicationCertificateMgtService()
+ .deleteCertificate(id, tenantDomain);
+ } catch (CertificateMgtException e) {
+ throw new IdentityApplicationManagementException("Error while deleting certificate", e);
}
}
@@ -5356,39 +5313,6 @@ private void setBlobValue(String value, PreparedStatement prepStmt, int index) t
}
}
- /**
- * Get string from inputStream of a blob
- *
- * @param is input stream
- * @return
- * @throws IOException
- */
- private String getBlobValue(InputStream is) throws IOException {
-
- if (is != null) {
- BufferedReader br = null;
- StringBuilder sb = new StringBuilder();
- String line;
- try {
- br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
- while ((line = br.readLine()) != null) {
- sb.append(line);
- }
- } finally {
- if (br != null) {
- try {
- br.close();
- } catch (IOException e) {
- log.error("Error in retrieving the Blob value", e);
- }
- }
- }
-
- return sb.toString();
- }
- return null;
- }
-
private void updateConfigurationsAsServiceProperties(ServiceProvider sp)
throws IdentityApplicationManagementException {
@@ -5852,10 +5776,13 @@ public String addApplication(ServiceProvider application,
addApplicationConfigurations(connection, application, tenantDomain);
IdentityDatabaseUtil.commitTransaction(connection);
return resourceId;
+ } catch (IdentityApplicationManagementClientException e) {
+ rollbackAddApplicationTransaction(connection, application, tenantDomain);
+ throw e;
} catch (SQLException | UserStoreException | IdentityApplicationManagementException e) {
log.error("Error while creating the application with name: " + application.getApplicationName()
+ " in tenantDomain: " + tenantDomain + ". Rolling back created application information.");
- IdentityDatabaseUtil.rollbackTransaction(connection);
+ rollbackAddApplicationTransaction(connection, application, tenantDomain);
if (isApplicationConflict(e)) {
throw new IdentityApplicationManagementClientException(APPLICATION_ALREADY_EXISTS.getCode(),
"Application already exists with name: " + application.getApplicationName()
@@ -5879,6 +5806,8 @@ public void updateApplicationByResourceId(String resourceId,
updatedApp.setApplicationID(appIdUsingResourceId);
updateApplication(updatedApp, tenantDomain);
+ } catch (IdentityApplicationManagementClientException e) {
+ throw e;
} catch (IdentityApplicationManagementException ex) {
// Send error code.
throw new IdentityApplicationManagementServerException("Error while updating application with resourceId: "
@@ -5922,7 +5851,7 @@ public void deleteApplicationByResourceId(String resourceId,
if (application != null) {
// Delete the application certificate if there is any
- deleteApplicationCertificate(connection, application);
+ deleteApplicationCertificate(application, tenantDomain);
// Delete android attestation service credentials if there is any
deleteAndroidAttestationCredentials(application);
@@ -6551,11 +6480,12 @@ private int getAppIdUsingResourceId(String resourceId)
return applicationId;
}
- private void deleteApplicationCertificate(Connection connection, ServiceProvider application) throws SQLException {
+ private void deleteApplicationCertificate(ServiceProvider application, String tenantDomain)
+ throws IdentityApplicationManagementException {
String certificateReferenceID = getCertificateReferenceID(application.getSpProperties());
if (certificateReferenceID != null) {
- deleteCertificate(connection, Integer.parseInt(certificateReferenceID));
+ deleteCertificate(Integer.parseInt(certificateReferenceID), tenantDomain);
}
}
@@ -6674,4 +6604,15 @@ public List getTrustedApps(PlatformType platformType) throws Identit
}
return trustedApps;
}
+
+ private void rollbackAddApplicationTransaction(Connection connection, ServiceProvider application,
+ String tenantDomain) throws IdentityApplicationManagementException {
+
+ try {
+ IdentityDatabaseUtil.rollbackTransaction(connection);
+ deleteApplicationCertificate(application, tenantDomain);
+ } catch (Exception e) {
+ throw new IdentityApplicationManagementException("Error while rolling back the transaction.", e);
+ }
+ }
}
diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationMgtDBQueries.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationMgtDBQueries.java
index b6ee788f9ccc..fc65dc521468 100644
--- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationMgtDBQueries.java
+++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/dao/impl/ApplicationMgtDBQueries.java
@@ -46,8 +46,16 @@ public class ApplicationMgtDBQueries {
public static final String UPDATE_BASIC_APPINFO_WITH_LOCAL_AND_OUTBOUND_CONFIGURATION = "UPDATE SP_APP SET " +
"IS_SEND_AUTH_LIST_OF_IDPS=?, IS_USE_TENANT_DOMAIN_SUBJECT=?, IS_USE_USER_DOMAIN_SUBJECT=?, " +
"ENABLE_AUTHORIZATION=?, SUBJECT_CLAIM_URI=?, AUTH_TYPE=? WHERE TENANT_ID= ? AND ID = ?";
+ /**
+ * @deprecated Use ApplicationCertificateMgtService instead.
+ */
+ @Deprecated
public static final String UPDATE_CERTIFICATE = "UPDATE IDN_CERTIFICATE SET CERTIFICATE_IN_PEM = ? WHERE " +
"ID = ?";
+ /**
+ * @deprecated Use ApplicationCertificateMgtService instead.
+ */
+ @Deprecated
public static final String ADD_CERTIFICATE = "INSERT INTO IDN_CERTIFICATE(NAME, CERTIFICATE_IN_PEM, TENANT_ID) " +
"VALUES(?, ?, ?)";
public static final String UPDATE_BASIC_APPINFO_WITH_PRO_PROPERTIES = "UPDATE SP_APP SET PROVISIONING_USERSTORE_" +
@@ -325,11 +333,31 @@ public class ApplicationMgtDBQueries {
public static final String DELETE_SP_METADATA = "DELETE FROM SP_METADATA WHERE SP_ID = ?";
+ /**
+ * @deprecated Use ApplicationCertificateMgtService instead.
+ */
+ @Deprecated
public static final String GET_CERTIFICATE_BY_ID = "SELECT CERTIFICATE_IN_PEM FROM IDN_CERTIFICATE WHERE ID = ?";
+ /**
+ * @deprecated Use ApplicationCertificateMgtService instead.
+ */
+ @Deprecated
public static final String GET_CERTIFICATE_ID_BY_NAME = "SELECT ID FROM IDN_CERTIFICATE WHERE NAME = ? AND " +
"TENANT_ID = ?";
+ /**
+ * @deprecated Use ApplicationCertificateMgtService instead.
+ */
+ @Deprecated
public static final String REMOVE_CERTIFICATE = "DELETE FROM IDN_CERTIFICATE WHERE ID = ?";
+ /**
+ * This query was previously used to delete all certificates associated with a tenant as part of tenant deletion.
+ * However, there is no product entry point for invoking this method directly. Since tenant deletion is managed
+ * as an administrative process, it is now recommended to handle certificate removal for a tenant through such
+ * process.
+ * @deprecated
+ */
+ @Deprecated
public static final String REMOVE_CERTIFICATES_BY_TENANT_ID = "DELETE FROM IDN_CERTIFICATE WHERE TENANT_ID = ?";
public static final String CHECK_AVAILABILITY_OF_IDN_CERTIFICATE_TABLE_MYSQL = "SELECT ID FROM IDN_CERTIFICATE " +
"LIMIT 1";
diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponent.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponent.java
index bca4581dc47d..986b2374dad9 100644
--- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponent.java
+++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponent.java
@@ -66,6 +66,7 @@
import org.wso2.carbon.identity.application.mgt.provider.RegistryBasedApplicationPermissionProvider;
import org.wso2.carbon.identity.application.mgt.validator.ApplicationValidator;
import org.wso2.carbon.identity.application.mgt.validator.DefaultApplicationValidator;
+import org.wso2.carbon.identity.certificate.management.service.ApplicationCertificateManagementService;
import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService;
import org.wso2.carbon.identity.claim.metadata.mgt.listener.ClaimMetadataMgtListener;
import org.wso2.carbon.identity.core.SAMLSSOServiceProviderManager;
@@ -635,4 +636,26 @@ private void unsetSecretResolveManagerService(SecretResolveManager secretResolve
ApplicationManagementServiceComponentHolder.getInstance().setSecretResolveManager(null);
}
+
+ @Reference(
+ name = "org.wso2.carbon.identity.certificate.management.service.ApplicationCertificateManagementService",
+ service = ApplicationCertificateManagementService.class,
+ cardinality = ReferenceCardinality.MANDATORY,
+ policy = ReferencePolicy.DYNAMIC,
+ unbind = "unsetApplicationCertificateManagementService"
+ )
+ protected void setApplicationCertificateManagementService(ApplicationCertificateManagementService
+ applicationCertificateManagementService) {
+
+ ApplicationManagementServiceComponentHolder.getInstance()
+ .setApplicationCertificateMgtService(applicationCertificateManagementService);
+ log.debug("ApplicationCertificateManagementService set in ApplicationManagementServiceComponent bundle.");
+ }
+
+ protected void unsetApplicationCertificateManagementService(ApplicationCertificateManagementService
+ applicationCertificateManagementService) {
+
+ ApplicationManagementServiceComponentHolder.getInstance().setApplicationCertificateMgtService(null);
+ log.debug("ApplicationCertificateManagementService unset in ApplicationManagementServiceComponent bundle.");
+ }
}
diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponentHolder.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponentHolder.java
index 758a552e24da..289cde9c84f8 100644
--- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponentHolder.java
+++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/main/java/org/wso2/carbon/identity/application/mgt/internal/ApplicationManagementServiceComponentHolder.java
@@ -22,6 +22,7 @@
import org.wso2.carbon.identity.application.mgt.AbstractInboundAuthenticatorConfig;
import org.wso2.carbon.identity.application.mgt.inbound.protocol.ApplicationInboundAuthConfigHandler;
import org.wso2.carbon.identity.application.mgt.provider.ApplicationPermissionProvider;
+import org.wso2.carbon.identity.certificate.management.service.ApplicationCertificateManagementService;
import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService;
import org.wso2.carbon.identity.core.SAMLSSOServiceProviderManager;
import org.wso2.carbon.identity.event.services.IdentityEventService;
@@ -79,6 +80,8 @@ public class ApplicationManagementServiceComponentHolder {
private SecretManager secretManager;
private SecretResolveManager secretResolveManager;
+ private ApplicationCertificateManagementService applicationCertificateMgtService;
+
private ApplicationManagementServiceComponentHolder() {
}
@@ -418,4 +421,23 @@ public List getApplicationInboundAuthConfig
return applicationInboundAuthConfigHandlers;
}
+
+ /**
+ * Gets the ApplicationCertificateManagementService instance.
+ * @return The ApplicationCertificateManagementService instance.
+ */
+ public ApplicationCertificateManagementService getApplicationCertificateMgtService() {
+
+ return applicationCertificateMgtService;
+ }
+
+ /**
+ * Sets the ApplicationCertificateManagementService instance.
+ * @param applicationCertificateMgtService The ApplicationCertificateManagementService instance to be set.
+ */
+ public void setApplicationCertificateMgtService(
+ ApplicationCertificateManagementService applicationCertificateMgtService) {
+
+ this.applicationCertificateMgtService = applicationCertificateMgtService;
+ }
}
diff --git a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/test/java/org/wso2/carbon/identity/application/mgt/ApplicationManagementServiceImplTest.java b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/test/java/org/wso2/carbon/identity/application/mgt/ApplicationManagementServiceImplTest.java
index ec71ddfe0732..38c6097fe252 100644
--- a/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/test/java/org/wso2/carbon/identity/application/mgt/ApplicationManagementServiceImplTest.java
+++ b/components/application-mgt/org.wso2.carbon.identity.application.mgt/src/test/java/org/wso2/carbon/identity/application/mgt/ApplicationManagementServiceImplTest.java
@@ -18,6 +18,7 @@
package org.wso2.carbon.identity.application.mgt;
+import org.apache.commons.lang.StringUtils;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.testng.Assert;
@@ -34,6 +35,7 @@
import org.wso2.carbon.identity.application.common.ApplicationAuthenticatorService;
import org.wso2.carbon.identity.application.common.IdentityApplicationManagementClientException;
import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
+import org.wso2.carbon.identity.application.common.IdentityApplicationManagementServerException;
import org.wso2.carbon.identity.application.common.model.ApplicationBasicInfo;
import org.wso2.carbon.identity.application.common.model.AuthenticationStep;
import org.wso2.carbon.identity.application.common.model.Claim;
@@ -54,8 +56,10 @@
import org.wso2.carbon.identity.application.common.model.RequestPathAuthenticatorConfig;
import org.wso2.carbon.identity.application.common.model.RoleMapping;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
+import org.wso2.carbon.identity.application.common.model.ServiceProviderProperty;
import org.wso2.carbon.identity.application.common.model.SpTrustedAppMetadata;
import org.wso2.carbon.identity.application.common.model.TrustedApp;
+import org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.PlatformType;
import org.wso2.carbon.identity.application.mgt.inbound.dto.ApplicationDTO;
import org.wso2.carbon.identity.application.mgt.inbound.dto.InboundProtocolConfigurationDTO;
import org.wso2.carbon.identity.application.mgt.inbound.dto.InboundProtocolsDTO;
@@ -64,6 +68,11 @@
import org.wso2.carbon.identity.application.mgt.provider.ApplicationPermissionProvider;
import org.wso2.carbon.identity.application.mgt.provider.RegistryBasedApplicationPermissionProvider;
import org.wso2.carbon.identity.base.AuthenticatorPropertyConstants.DefinedByType;
+import org.wso2.carbon.identity.certificate.management.exception.CertificateMgtClientException;
+import org.wso2.carbon.identity.certificate.management.exception.CertificateMgtException;
+import org.wso2.carbon.identity.certificate.management.exception.CertificateMgtServerException;
+import org.wso2.carbon.identity.certificate.management.model.Certificate;
+import org.wso2.carbon.identity.certificate.management.service.ApplicationCertificateManagementService;
import org.wso2.carbon.identity.common.testng.WithH2Database;
import org.wso2.carbon.identity.common.testng.realm.InMemoryRealmService;
import org.wso2.carbon.identity.common.testng.realm.MockUserStoreManager;
@@ -99,14 +108,19 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Optional;
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
import static org.wso2.carbon.CarbonConstants.REGISTRY_SYSTEM_USERNAME;
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.PlatformType;
@@ -114,6 +128,7 @@
import static org.wso2.carbon.identity.application.common.util.IdentityApplicationConstants.TEMPLATE_VERSION_SP_PROPERTY_NAME;
import static org.wso2.carbon.identity.application.mgt.ApplicationConstants.PORTAL_NAMES_CONFIG_ELEMENT;
import static org.wso2.carbon.identity.application.mgt.ApplicationConstants.TRUSTED_APP_CONSENT_REQUIRED_PROPERTY;
+import static org.wso2.carbon.identity.certificate.management.constant.CertificateMgtErrors.ERROR_INVALID_CERTIFICATE_CONTENT;
import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
import static org.wso2.carbon.utils.multitenancy.MultitenantConstants.SUPER_TENANT_ID;
@@ -154,9 +169,19 @@ public class ApplicationManagementServiceImplTest {
private static final String ANDROID_PACKAGE_NAME_1 = "com.wso2.sample.mobile.application";
private static final String ANDROID_PACKAGE_NAME_2 = "com.wso2.sample.mobile.application2";
private static final String APPLE_APP_ID = "APPLETEAMID.com.wso2.mobile.sample";
+ private static final String CERTIFICATE = "dummy_application_certificate";
+ private static final String UPDATED_CERTIFICATE = "updated_dummy_application_certificate";
+ private static final int CERTIFICATE_ID = 1;
private IdPManagementDAO idPManagementDAO;
private ApplicationManagementServiceImpl applicationManagementService;
+ private ApplicationCertificateManagementService applicationCertificateManagementService;
+
+ private String appIdWithCert;
+ private ServiceProvider appWithCert;
+ private Certificate certificate;
+ private CertificateMgtServerException serverException;
+ private CertificateMgtClientException clientException;
@BeforeClass
public void setup() throws RegistryException, UserStoreException, SecretManagementException {
@@ -190,6 +215,19 @@ public void setup() throws RegistryException, UserStoreException, SecretManageme
CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME = false;
MockedStatic definedByType = mockStatic(DefinedByType.class);
definedByType.when(() -> DefinedByType.valueOf(anyString())).thenReturn(DefinedByType.SYSTEM);
+
+ applicationCertificateManagementService = mock(ApplicationCertificateManagementService.class);
+ ApplicationManagementServiceComponentHolder.getInstance()
+ .setApplicationCertificateMgtService(applicationCertificateManagementService);
+ certificate = new Certificate.Builder()
+ .id(String.valueOf(CERTIFICATE_ID))
+ .name(APPLICATION_NAME_1)
+ .certificateContent(CERTIFICATE)
+ .build();
+ serverException = new CertificateMgtServerException("server_error_message", "server_error_description", "65010",
+ new Throwable());
+ clientException = new CertificateMgtClientException(ERROR_INVALID_CERTIFICATE_CONTENT.getMessage(),
+ ERROR_INVALID_CERTIFICATE_CONTENT.getDescription(), ERROR_INVALID_CERTIFICATE_CONTENT.getCode());
}
@DataProvider(name = "addApplicationDataProvider")
@@ -1328,6 +1366,287 @@ public void addApplicationWithTemplateIdAndTemplateVersionData(String templateId
REGISTRY_SYSTEM_USERNAME);
}
+ @Test(groups = "certificate", priority = 1)
+ public void testAddApplicationWithCertificate() throws CertificateMgtException {
+
+ ServiceProvider inputSP = new ServiceProvider();
+ inputSP.setApplicationName(APPLICATION_NAME_1);
+ inputSP.setCertificateContent(certificate.getCertificateContent());
+ addApplicationConfigurations(inputSP);
+
+ doReturn(0).when(applicationCertificateManagementService).addCertificate(any(), anyString());
+ doReturn(certificate).when(applicationCertificateManagementService).getCertificateByName(any(), anyString());
+ try {
+ appIdWithCert = applicationManagementService.createApplication(inputSP, SUPER_TENANT_DOMAIN_NAME,
+ REGISTRY_SYSTEM_USERNAME);
+ } catch (Exception e) {
+ Assert.fail("Application addition with certificate addition should be successful without any exceptions");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 2, dependsOnMethods = "testAddApplicationWithCertificate")
+ public void testGetApplicationWithServerErrorWhenRetrievingCert() throws CertificateMgtException {
+
+ doThrow(serverException).when(applicationCertificateManagementService).getCertificate(anyInt(), anyString());
+ try {
+ applicationManagementService.getApplicationByResourceId(appIdWithCert, SUPER_TENANT_DOMAIN_NAME);
+ Assert.fail("Successful retrieval of the application without an exception is considered as a failure");
+ } catch (IdentityApplicationManagementException e) {
+ Assert.assertEquals(e.getClass(), IdentityApplicationManagementServerException.class);
+ Assert.assertTrue(e.getMessage().contains("Error while retrieving application with resourceId: "
+ + appIdWithCert + " in tenantDomain: " + SUPER_TENANT_DOMAIN_NAME));
+ for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) {
+ if (cause instanceof CertificateMgtServerException) {
+ return;
+ }
+ }
+ Assert.fail("Expected cause of type CertificateMgtServerException was not found in the exception chain");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 3, dependsOnMethods = "testAddApplicationWithCertificate")
+ public void testGetApplicationWithCertificate() throws IdentityApplicationManagementException,
+ CertificateMgtException {
+
+ reset(applicationCertificateManagementService);
+ when(applicationCertificateManagementService.getCertificate(anyInt(), anyString())).thenReturn(certificate);
+ appWithCert = applicationManagementService.getApplicationByResourceId(appIdWithCert, SUPER_TENANT_DOMAIN_NAME);
+
+ Optional certificateValue = Arrays.stream(appWithCert.getSpProperties())
+ .filter(prop -> "CERTIFICATE".equals(prop.getName()))
+ .map(ServiceProviderProperty::getValue)
+ .findFirst();
+ Assert.assertTrue(certificateValue.isPresent(), "Certificate property not found");
+ Assert.assertEquals(Integer.parseInt(certificateValue.get()), CERTIFICATE_ID);
+ Assert.assertEquals(appWithCert.getCertificateContent(), certificate.getCertificateContent());
+ }
+
+ @Test(groups = "certificate", priority = 4, dependsOnMethods = {"testAddApplicationWithCertificate",
+ "testGetApplicationWithCertificate"})
+ public void testUpdateApplicationWithCertificate() throws CertificateMgtException {
+
+ doNothing().when(applicationCertificateManagementService).updateCertificateContent(anyInt(), anyString(),
+ anyString());
+ try {
+ appWithCert.setCertificateContent(UPDATED_CERTIFICATE);
+ applicationManagementService.updateApplicationByResourceId(appIdWithCert, appWithCert,
+ SUPER_TENANT_DOMAIN_NAME, REGISTRY_SYSTEM_USERNAME);
+ } catch (Exception e) {
+ Assert.fail("Application update with certificate update should be successful without any exceptions");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 5, dependsOnMethods = {"testAddApplicationWithCertificate",
+ "testGetApplicationWithCertificate"})
+ public void testUpdateApplicationWithServerErrorWhenUpdatingCert() throws CertificateMgtException {
+
+ reset(applicationCertificateManagementService);
+ doThrow(serverException).when(applicationCertificateManagementService).updateCertificateContent(anyInt(),
+ anyString(), anyString());
+ try {
+ appWithCert.setCertificateContent(UPDATED_CERTIFICATE);
+ applicationManagementService.updateApplicationByResourceId(appIdWithCert, appWithCert,
+ SUPER_TENANT_DOMAIN_NAME, REGISTRY_SYSTEM_USERNAME);
+ Assert.fail("Successful update of the application without an exception is considered as a failure");
+ } catch (IdentityApplicationManagementException e) {
+ Assert.assertEquals(e.getClass(), IdentityApplicationManagementServerException.class);
+ Assert.assertTrue(e.getMessage().contains("Error while updating application with resourceId: "
+ + appIdWithCert + " in tenantDomain: " + SUPER_TENANT_DOMAIN_NAME));
+ for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) {
+ if (cause instanceof CertificateMgtServerException) {
+ return;
+ }
+ }
+ Assert.fail("Expected cause of type CertificateMgtServerException was not found in the exception chain");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 6, dependsOnMethods = {"testAddApplicationWithCertificate",
+ "testGetApplicationWithCertificate"})
+ public void testUpdateApplicationWithClientErrorWhenUpdatingCert() throws CertificateMgtException {
+
+ reset(applicationCertificateManagementService);
+ doThrow(clientException).when(applicationCertificateManagementService).updateCertificateContent(anyInt(),
+ anyString(), anyString());
+ try {
+ appWithCert.setCertificateContent(UPDATED_CERTIFICATE);
+ applicationManagementService.updateApplicationByResourceId(appIdWithCert, appWithCert,
+ SUPER_TENANT_DOMAIN_NAME, REGISTRY_SYSTEM_USERNAME);
+ Assert.fail("Successful update of the application without an exception is considered as a failure");
+ } catch (IdentityApplicationManagementException e) {
+ Assert.assertEquals(e.getClass(), IdentityApplicationManagementClientException.class);
+ Assert.assertEquals(e.getMessage(), clientException.getDescription());
+ for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) {
+ if (cause instanceof CertificateMgtClientException) {
+ return;
+ }
+ }
+ Assert.fail("Expected cause of type CertificateMgtClientException was not found in the exception chain");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 7, dependsOnMethods = {"testAddApplicationWithCertificate",
+ "testGetApplicationWithCertificate"})
+ public void testUpdateApplicationWithServerErrorWhenDeletingCert() throws CertificateMgtException {
+
+ doThrow(serverException).when(applicationCertificateManagementService).deleteCertificate(anyInt(), anyString());
+ try {
+ appWithCert.setCertificateContent(StringUtils.EMPTY);
+ applicationManagementService.updateApplicationByResourceId(appIdWithCert, appWithCert,
+ SUPER_TENANT_DOMAIN_NAME, REGISTRY_SYSTEM_USERNAME);
+ Assert.fail("Successful update of the application without an exception is considered as a failure");
+ } catch (IdentityApplicationManagementException e) {
+ Assert.assertEquals(e.getClass(), IdentityApplicationManagementServerException.class);
+ Assert.assertTrue(e.getMessage().contains("Error while updating application with resourceId: "
+ + appIdWithCert + " in tenantDomain: " + SUPER_TENANT_DOMAIN_NAME));
+ for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) {
+ if (cause instanceof CertificateMgtServerException) {
+ return;
+ }
+ }
+ Assert.fail("Expected cause of type CertificateMgtServerException was not found in the exception chain");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 8, dependsOnMethods = {"testAddApplicationWithCertificate",
+ "testGetApplicationWithCertificate"})
+ public void testDeleteApplicationWithCertificate() throws IdentityApplicationManagementException,
+ CertificateMgtException {
+
+ reset(applicationCertificateManagementService);
+ doNothing().when(applicationCertificateManagementService).deleteCertificate(anyInt(), anyString());
+ try {
+ appWithCert.setCertificateContent(StringUtils.EMPTY);
+ applicationManagementService.updateApplicationByResourceId(appIdWithCert, appWithCert,
+ SUPER_TENANT_DOMAIN_NAME, REGISTRY_SYSTEM_USERNAME);
+ } catch (Exception e) {
+ Assert.fail("Application update with certificate deletion should be successful without any exceptions");
+ }
+
+ appWithCert = applicationManagementService.getApplicationByResourceId(appIdWithCert, SUPER_TENANT_DOMAIN_NAME);
+ Optional certificateValue = Arrays.stream(appWithCert.getSpProperties())
+ .filter(prop -> "CERTIFICATE".equals(prop.getName()))
+ .map(ServiceProviderProperty::getValue)
+ .findFirst();
+ Assert.assertFalse(certificateValue.isPresent(), "Certificate property should be removed");
+ Assert.assertNull(appWithCert.getCertificateContent());
+
+ // Deleting added application.
+ doNothing().when(applicationCertificateManagementService).deleteCertificate(anyInt(), anyString());
+ applicationManagementService.deleteApplication(appWithCert.getApplicationName(),
+ SUPER_TENANT_DOMAIN_NAME, REGISTRY_SYSTEM_USERNAME);
+ }
+
+ @Test(groups = "certificate", priority = 9)
+ public void testAddApplicationWithServerErrorWhenAddingCert() throws CertificateMgtException {
+
+ ServiceProvider inputSP = new ServiceProvider();
+ inputSP.setApplicationName(APPLICATION_NAME_1);
+ inputSP.setCertificateContent(certificate.getCertificateContent());
+ addApplicationConfigurations(inputSP);
+
+ reset(applicationCertificateManagementService);
+ doThrow(serverException).when(applicationCertificateManagementService).addCertificate(any(), anyString());
+ try {
+ appIdWithCert = applicationManagementService.createApplication(inputSP, SUPER_TENANT_DOMAIN_NAME,
+ REGISTRY_SYSTEM_USERNAME);
+ Assert.fail("Successful creation of the application without an exception is considered as a failure");
+ } catch (IdentityApplicationManagementException e) {
+ Assert.assertTrue(e.getMessage().contains("Error while creating an application: "
+ + inputSP.getApplicationName() + " in tenantDomain: " + SUPER_TENANT_DOMAIN_NAME));
+ for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) {
+ if (cause instanceof CertificateMgtServerException) {
+ return;
+ }
+ }
+ Assert.fail("Expected cause of type CertificateMgtServerException was not found in the exception chain");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 10)
+ public void testAddApplicationWithClientErrorWhenAddingCert() throws CertificateMgtException {
+
+ ServiceProvider inputSP = new ServiceProvider();
+ inputSP.setApplicationName(APPLICATION_NAME_1);
+ inputSP.setCertificateContent(certificate.getCertificateContent());
+ addApplicationConfigurations(inputSP);
+
+ reset(applicationCertificateManagementService);
+ doThrow(clientException).when(applicationCertificateManagementService).addCertificate(any(), anyString());
+ try {
+ appIdWithCert = applicationManagementService.createApplication(inputSP, SUPER_TENANT_DOMAIN_NAME,
+ REGISTRY_SYSTEM_USERNAME);
+ Assert.fail("Successful creation of the application without an exception is considered as a failure");
+ } catch (IdentityApplicationManagementException e) {
+ Assert.assertEquals(e.getClass(), IdentityApplicationManagementClientException.class);
+ Assert.assertEquals(e.getMessage(), clientException.getDescription());
+ for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) {
+ if (cause instanceof CertificateMgtClientException) {
+ return;
+ }
+ }
+ Assert.fail("Expected cause of type CertificateMgtClientException was not found in the exception chain");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 11)
+ public void testAddApplicationWithServerErrorWhenRetrievingCertByName() throws CertificateMgtException {
+
+ ServiceProvider inputSP = new ServiceProvider();
+ inputSP.setApplicationName(APPLICATION_NAME_1);
+ inputSP.setCertificateContent(certificate.getCertificateContent());
+ addApplicationConfigurations(inputSP);
+
+ reset(applicationCertificateManagementService);
+ doReturn(0).when(applicationCertificateManagementService).addCertificate(any(), anyString());
+ doThrow(serverException).when(applicationCertificateManagementService).getCertificateByName(any(),
+ anyString());
+ try {
+ appIdWithCert = applicationManagementService.createApplication(inputSP, SUPER_TENANT_DOMAIN_NAME,
+ REGISTRY_SYSTEM_USERNAME);
+ Assert.fail("Successful creation of the application without an exception is considered as a failure");
+ } catch (IdentityApplicationManagementException e) {
+ Assert.assertTrue(e.getMessage().contains("Error while creating an application: "
+ + inputSP.getApplicationName() + " in tenantDomain: " + SUPER_TENANT_DOMAIN_NAME));
+ for (Throwable cause = e.getCause(); cause != null; cause = cause.getCause()) {
+ if (cause instanceof CertificateMgtServerException) {
+ return;
+ }
+ }
+ Assert.fail("Expected cause of type CertificateMgtServerException was not found in the exception chain");
+ }
+ }
+
+ @Test(groups = "certificate", priority = 12)
+ public void testAddCertificateToExistingApplication() throws IdentityApplicationManagementException,
+ CertificateMgtException {
+
+ ServiceProvider inputSP = new ServiceProvider();
+ inputSP.setApplicationName(APPLICATION_NAME_2);
+ addApplicationConfigurations(inputSP);
+
+ String appIdWithoutCert = applicationManagementService.createApplication(inputSP, SUPER_TENANT_DOMAIN_NAME,
+ REGISTRY_SYSTEM_USERNAME);
+ ServiceProvider appWithoutCert = applicationManagementService.getApplicationByResourceId(appIdWithoutCert,
+ SUPER_TENANT_DOMAIN_NAME);
+
+ reset(applicationCertificateManagementService);
+ doReturn(2).when(applicationCertificateManagementService).addCertificate(any(), anyString());
+
+ try {
+ appWithoutCert.setCertificateContent(certificate.getCertificateContent());
+ applicationManagementService.updateApplicationByResourceId(appIdWithoutCert, appWithoutCert,
+ SUPER_TENANT_DOMAIN_NAME, REGISTRY_SYSTEM_USERNAME);
+ } catch (Exception e) {
+ Assert.fail("Application update with certificate addition should be successful without any exceptions");
+ }
+
+ // Deleting added application.
+ doNothing().when(applicationCertificateManagementService).deleteCertificate(anyInt(), anyString());
+ applicationManagementService.deleteApplication(appWithoutCert.getApplicationName(),
+ SUPER_TENANT_DOMAIN_NAME, REGISTRY_SYSTEM_USERNAME);
+ }
+
private void addApplicationConfigurations(ServiceProvider serviceProvider) {
serviceProvider.setDescription("Created for testing");