From 2d706b4b84a090797a4384ad71f8c93a570cb7a2 Mon Sep 17 00:00:00 2001 From: hwupathum Date: Thu, 15 Jun 2023 16:54:50 +0530 Subject: [PATCH 1/2] Create interface SAMLSSOServiceProviderDAORegistryImpl --- .../core/SAMLSSOServiceProviderManager.java | 3 +- .../core/dao/SAMLSSOServiceProviderDAO.java | 841 +---------------- ...SAMLSSOServiceProviderRegistryDAOImpl.java | 857 ++++++++++++++++++ .../IdentityPersistenceManager.java | 13 +- .../dao/SAMLSSOServiceProviderDAOTest.java | 28 +- 5 files changed, 918 insertions(+), 824 deletions(-) create mode 100644 components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderRegistryDAOImpl.java diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java index d9d0cde6c95d..97b068372bdc 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java @@ -22,6 +22,7 @@ import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderDAO; +import org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderRegistryDAOImpl; import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; import org.wso2.carbon.registry.api.RegistryException; @@ -44,7 +45,7 @@ public class SAMLSSOServiceProviderManager { private SAMLSSOServiceProviderDAO buildSAMLSSOProvider(int tenantId) throws RegistryException { Registry registry = IdentityTenantUtil.getRegistryService().getConfigSystemRegistry(tenantId); - return new SAMLSSOServiceProviderDAO(registry); + return new SAMLSSOServiceProviderRegistryDAOImpl(registry); } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAO.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAO.java index 67121c02db9b..ad59bf39d5de 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAO.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAO.java @@ -1,478 +1,36 @@ /* - * Copyright 2005-2007 WSO2, Inc. (http://wso2.com) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * Copyright (c) (2005-2023), WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. 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. + * + * 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.identity.core.dao; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; import org.wso2.carbon.identity.base.IdentityException; -import org.wso2.carbon.identity.core.CertificateRetriever; -import org.wso2.carbon.identity.core.CertificateRetrievingException; -import org.wso2.carbon.identity.core.DatabaseCertificateRetriever; -import org.wso2.carbon.identity.core.IdentityRegistryResources; -import org.wso2.carbon.identity.core.KeyStoreCertificateRetriever; import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO; -import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; -import org.wso2.carbon.identity.core.util.IdentityTenantUtil; -import org.wso2.carbon.registry.core.Collection; -import org.wso2.carbon.registry.core.Registry; -import org.wso2.carbon.registry.core.Resource; -import org.wso2.carbon.registry.core.exceptions.RegistryException; -import org.wso2.carbon.registry.core.jdbc.utils.Transaction; -import org.wso2.carbon.registry.core.session.UserRegistry; -import org.wso2.carbon.user.api.Tenant; -import org.wso2.carbon.user.api.UserStoreException; -import java.security.cert.X509Certificate; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import static org.wso2.carbon.identity.core.util.JdbcUtils.isH2DB; - -public class SAMLSSOServiceProviderDAO extends AbstractDAO { - - private static final String CERTIFICATE_PROPERTY_NAME = "CERTIFICATE"; - private static final String QUERY_TO_GET_APPLICATION_CERTIFICATE_ID = "SELECT " + - "META.VALUE FROM SP_INBOUND_AUTH INBOUND, SP_APP SP, SP_METADATA META WHERE SP.ID = INBOUND.APP_ID AND " + - "SP.ID = META.SP_ID AND META.NAME = ? AND INBOUND.INBOUND_AUTH_KEY = ? AND META.TENANT_ID = ?"; - - private static final String QUERY_TO_GET_APPLICATION_CERTIFICATE_ID_H2 = "SELECT " + - "META.`VALUE` FROM SP_INBOUND_AUTH INBOUND, SP_APP SP, SP_METADATA META WHERE SP.ID = INBOUND.APP_ID AND " + - "SP.ID = META.SP_ID AND META.NAME = ? AND INBOUND.INBOUND_AUTH_KEY = ? AND META.TENANT_ID = ?"; - - private static Log log = LogFactory.getLog(SAMLSSOServiceProviderDAO.class); - - public SAMLSSOServiceProviderDAO(Registry registry) { - this.registry = registry; - } - - protected SAMLSSOServiceProviderDO resourceToObject(Resource resource) { - SAMLSSOServiceProviderDO serviceProviderDO = new SAMLSSOServiceProviderDO(); - serviceProviderDO.setIssuer(resource - .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER)); - serviceProviderDO.setAssertionConsumerUrls(resource.getPropertyValues( - IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_CONS_URLS)); - serviceProviderDO.setDefaultAssertionConsumerUrl(resource.getProperty( - IdentityRegistryResources.PROP_DEFAULT_SAML_SSO_ASSERTION_CONS_URL)); - serviceProviderDO.setCertAlias(resource - .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_CERT_ALIAS)); - - if (StringUtils.isNotEmpty(resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_SIGNING_ALGORITHM))) { - serviceProviderDO.setSigningAlgorithmUri(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SSO_SIGNING_ALGORITHM)); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED) != - null) { - serviceProviderDO.setAssertionQueryRequestProfileEnabled(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED).trim())); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES) != - null) { - serviceProviderDO.setSupportedAssertionQueryRequestTypes(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES).trim()); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_SAML2_ARTIFACT_BINDING) != - null) { - serviceProviderDO.setEnableSAML2ArtifactBinding(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_ENABLE_SAML2_ARTIFACT_BINDING).trim())); - } - - if (StringUtils.isNotEmpty(resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DIGEST_ALGORITHM))) { - serviceProviderDO.setDigestAlgorithmUri(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SSO_DIGEST_ALGORITHM)); - } - - if (StringUtils.isNotEmpty(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SSO_ASSERTION_ENCRYPTION_ALGORITHM))) { - serviceProviderDO.setAssertionEncryptionAlgorithmUri(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SSO_ASSERTION_ENCRYPTION_ALGORITHM)); - } - - if (StringUtils.isNotEmpty(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SSO_KEY_ENCRYPTION_ALGORITHM))) { - serviceProviderDO.setKeyEncryptionAlgorithmUri(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SSO_KEY_ENCRYPTION_ALGORITHM)); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SINGLE_LOGOUT) != null) { - serviceProviderDO.setDoSingleLogout(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_DO_SINGLE_LOGOUT).trim())); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_NAMEID_FORMAT) != null) { - serviceProviderDO.setNameIDFormat(resource. - getProperty(IdentityRegistryResources.PROP_SAML_SSO_NAMEID_FORMAT)); - } - - if (resource - .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_NAMEID_CLAIMURI) != null) { - if (Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_ENABLE_NAMEID_CLAIMURI).trim())) { - serviceProviderDO.setNameIdClaimUri(resource. - getProperty(IdentityRegistryResources.PROP_SAML_SSO_NAMEID_CLAIMURI)); - } - } - - serviceProviderDO.setLoginPageURL(resource. - getProperty(IdentityRegistryResources.PROP_SAML_SSO_LOGIN_PAGE_URL)); - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_RESPONSE) != null) { - serviceProviderDO.setDoSignResponse(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_RESPONSE).trim())); - } - - if (serviceProviderDO.isDoSingleLogout()) { - serviceProviderDO.setSloResponseURL(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SLO_RESPONSE_URL)); - serviceProviderDO.setSloRequestURL(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SLO_REQUEST_URL)); - // Check front channel logout enable. - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_FRONT_CHANNEL_LOGOUT) != null) { - serviceProviderDO.setDoFrontChannelLogout(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_DO_FRONT_CHANNEL_LOGOUT).trim())); - if (serviceProviderDO.isDoFrontChannelLogout()) { - if (resource.getProperty(IdentityRegistryResources. - PROP_SAML_SSO_FRONT_CHANNEL_LOGOUT_BINDING) != null) { - serviceProviderDO.setFrontChannelLogoutBinding(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_FRONT_CHANNEL_LOGOUT_BINDING)); - } else { - // Default is redirect-binding. - serviceProviderDO.setFrontChannelLogoutBinding(IdentityRegistryResources - .DEFAULT_FRONT_CHANNEL_LOGOUT_BINDING); - } - - } - } - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_ASSERTIONS) != null) { - serviceProviderDO.setDoSignAssertions(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_ASSERTIONS).trim())); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_ENABLE_ECP) != null) { - serviceProviderDO.setSamlECP(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_ENABLE_ECP).trim())); - } - - if (resource - .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ATTRIB_CONSUMING_SERVICE_INDEX) != null) { - serviceProviderDO - .setAttributeConsumingServiceIndex(resource - .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ATTRIB_CONSUMING_SERVICE_INDEX)); - } else { - // Specific DB's (like oracle) returns empty strings as null. - serviceProviderDO.setAttributeConsumingServiceIndex(""); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_CLAIMS) != null) { - serviceProviderDO.setRequestedClaims(resource - .getPropertyValues(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_CLAIMS)); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_AUDIENCES) != null) { - serviceProviderDO.setRequestedAudiences(resource - .getPropertyValues(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_AUDIENCES)); - } - - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_RECIPIENTS) != null) { - serviceProviderDO.setRequestedRecipients(resource - .getPropertyValues(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_RECIPIENTS)); - } - - if (resource - .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ATTRIBUTES_BY_DEFAULT) != null) { - String enableAttrByDefault = resource - .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ATTRIBUTES_BY_DEFAULT); - serviceProviderDO.setEnableAttributesByDefault(Boolean.valueOf(enableAttrByDefault)); - } - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_IDP_INIT_SSO_ENABLED) != null) { - serviceProviderDO.setIdPInitSSOEnabled(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_IDP_INIT_SSO_ENABLED).trim())); - } - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SLO_IDP_INIT_SLO_ENABLED) != null) { - serviceProviderDO.setIdPInitSLOEnabled(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SLO_IDP_INIT_SLO_ENABLED).trim())); - if (serviceProviderDO.isIdPInitSLOEnabled() && resource.getProperty( - IdentityRegistryResources.PROP_SAML_IDP_INIT_SLO_RETURN_URLS) != null) { - serviceProviderDO.setIdpInitSLOReturnToURLs(resource.getPropertyValues( - IdentityRegistryResources.PROP_SAML_IDP_INIT_SLO_RETURN_URLS)); - } - } - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ENCRYPTED_ASSERTION) != null) { - serviceProviderDO.setDoEnableEncryptedAssertion(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ENCRYPTED_ASSERTION).trim())); - } - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_REQUESTS) != null) { - serviceProviderDO.setDoValidateSignatureInRequests(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_REQUESTS).trim())); - } - if (resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE) != null) { - serviceProviderDO.setDoValidateSignatureInArtifactResolve(Boolean.valueOf(resource.getProperty( - IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE).trim())); - } - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_QUALIFIER) != null) { - serviceProviderDO.setIssuerQualifier(resource - .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_QUALIFIER)); - } - if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_IDP_ENTITY_ID_ALIAS) != null) { - serviceProviderDO.setIdpEntityIDAlias(resource.getProperty(IdentityRegistryResources - .PROP_SAML_SSO_IDP_ENTITY_ID_ALIAS)); - } - return serviceProviderDO; - } +public interface SAMLSSOServiceProviderDAO { /** * Add the service provider information to the registry. + * * @param serviceProviderDO Service provider information object. * @return True if addition successful. * @throws IdentityException Error while persisting to the registry. */ - public boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws IdentityException { - - if (serviceProviderDO == null || serviceProviderDO.getIssuer() == null || - StringUtils.isBlank(serviceProviderDO.getIssuer())) { - throw new IdentityException("Issuer cannot be found in the provided arguments."); - } - - // If an issuer qualifier value is specified, it is appended to the end of the issuer value. - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - serviceProviderDO.setIssuer(getIssuerWithQualifier(serviceProviderDO.getIssuer(), - serviceProviderDO.getIssuerQualifier())); - } - - String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(serviceProviderDO.getIssuer()); - - boolean isTransactionStarted = Transaction.isStarted(); - boolean isErrorOccurred = false; - try { - if (registry.resourceExists(path)) { - if (log.isDebugEnabled()) { - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - log.debug("SAML2 Service Provider already exists with the same issuer name " - + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier name " - + serviceProviderDO.getIssuerQualifier()); - } else { - log.debug("SAML2 Service Provider already exists with the same issuer name " - + serviceProviderDO.getIssuer()); - } - } - return false; - } - - Resource resource = createResource(serviceProviderDO); - if (!isTransactionStarted) { - registry.beginTransaction(); - } - registry.put(path, resource); - if (log.isDebugEnabled()) { - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " with issuer " - + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier " + - serviceProviderDO.getIssuerQualifier() + " is added successfully."); - } else { - log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " is added successfully."); - } - } - return true; - } catch (RegistryException e) { - isErrorOccurred = true; - String msg; - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - msg = "Error while adding SAML2 Service Provider for issuer: " + getIssuerWithoutQualifier - (serviceProviderDO.getIssuer()) + " and qualifier name " + serviceProviderDO - .getIssuerQualifier(); - } else { - msg = "Error while adding SAML2 Service Provider for issuer: " + serviceProviderDO.getIssuer(); - } - log.error(msg, e); - throw IdentityException.error(msg, e); - } finally { - commitOrRollbackTransaction(isErrorOccurred); - } - } - - private Resource createResource(SAMLSSOServiceProviderDO serviceProviderDO) throws RegistryException { - Resource resource; - resource = registry.newResource(); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER, - serviceProviderDO.getIssuer()); - resource.setProperty(IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_CONS_URLS, - serviceProviderDO.getAssertionConsumerUrlList()); - resource.addProperty(IdentityRegistryResources.PROP_DEFAULT_SAML_SSO_ASSERTION_CONS_URL, - serviceProviderDO.getDefaultAssertionConsumerUrl()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_CERT_ALIAS, - serviceProviderDO.getCertAlias()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_LOGIN_PAGE_URL, - serviceProviderDO.getLoginPageURL()); - resource.addProperty( - IdentityRegistryResources.PROP_SAML_SSO_NAMEID_FORMAT, - serviceProviderDO.getNameIDFormat()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_SIGNING_ALGORITHM, serviceProviderDO - .getSigningAlgorithmUri()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DIGEST_ALGORITHM, serviceProviderDO - .getDigestAlgorithmUri()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_ENCRYPTION_ALGORITHM, serviceProviderDO - .getAssertionEncryptionAlgorithmUri()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_KEY_ENCRYPTION_ALGORITHM, serviceProviderDO - .getKeyEncryptionAlgorithmUri()); - if (serviceProviderDO.getNameIdClaimUri() != null - && serviceProviderDO.getNameIdClaimUri().trim().length() > 0) { - resource.addProperty( - IdentityRegistryResources.PROP_SAML_SSO_ENABLE_NAMEID_CLAIMURI, - "true"); - resource.addProperty( - IdentityRegistryResources.PROP_SAML_SSO_NAMEID_CLAIMURI, - serviceProviderDO.getNameIdClaimUri()); - } else { - resource.addProperty( - IdentityRegistryResources.PROP_SAML_SSO_ENABLE_NAMEID_CLAIMURI, - "false"); - } - - String doSingleLogout = String.valueOf(serviceProviderDO.isDoSingleLogout()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SINGLE_LOGOUT, doSingleLogout); - if (serviceProviderDO.isDoSingleLogout()) { - if (StringUtils.isNotBlank(serviceProviderDO.getSloResponseURL())) { - resource.addProperty(IdentityRegistryResources.PROP_SAML_SLO_RESPONSE_URL, - serviceProviderDO.getSloResponseURL()); - } - if (StringUtils.isNotBlank(serviceProviderDO.getSloRequestURL())) { - resource.addProperty(IdentityRegistryResources.PROP_SAML_SLO_REQUEST_URL, - serviceProviderDO.getSloRequestURL()); - } - // Create doFrontChannelLogout property in the registry. - String doFrontChannelLogout = String.valueOf(serviceProviderDO.isDoFrontChannelLogout()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_FRONT_CHANNEL_LOGOUT, doFrontChannelLogout); - if (serviceProviderDO.isDoFrontChannelLogout()) { - // Create frontChannelLogoutMethod property in the registry. - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_FRONT_CHANNEL_LOGOUT_BINDING, - serviceProviderDO.getFrontChannelLogoutBinding()); - } - } - - String doSignResponse = String.valueOf(serviceProviderDO.isDoSignResponse()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_RESPONSE, - doSignResponse); - String isAssertionQueryRequestProfileEnabled = String.valueOf(serviceProviderDO - .isAssertionQueryRequestProfileEnabled()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED, - isAssertionQueryRequestProfileEnabled); - String supportedAssertionQueryRequestTypes = serviceProviderDO.getSupportedAssertionQueryRequestTypes(); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES, - supportedAssertionQueryRequestTypes); - String isEnableSAML2ArtifactBinding = String.valueOf(serviceProviderDO - .isEnableSAML2ArtifactBinding()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_SAML2_ARTIFACT_BINDING, - isEnableSAML2ArtifactBinding); - String doSignAssertions = String.valueOf(serviceProviderDO.isDoSignAssertions()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_ASSERTIONS, - doSignAssertions); - String isSamlECP = String.valueOf(serviceProviderDO.isSamlECP()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_ENABLE_ECP, - isSamlECP); - if (CollectionUtils.isNotEmpty(serviceProviderDO.getRequestedClaimsList())) { - resource.setProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_CLAIMS, - serviceProviderDO.getRequestedClaimsList()); - } - if (serviceProviderDO.getAttributeConsumingServiceIndex() != null) { - resource.addProperty( - IdentityRegistryResources.PROP_SAML_SSO_ATTRIB_CONSUMING_SERVICE_INDEX, - serviceProviderDO.getAttributeConsumingServiceIndex()); - } - if (CollectionUtils.isNotEmpty(serviceProviderDO.getRequestedAudiencesList())) { - resource.setProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_AUDIENCES, - serviceProviderDO.getRequestedAudiencesList()); - } - if (CollectionUtils.isNotEmpty(serviceProviderDO.getRequestedRecipientsList())) { - resource.setProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_RECIPIENTS, - serviceProviderDO.getRequestedRecipientsList()); - } - - String enableAttributesByDefault = String.valueOf(serviceProviderDO.isEnableAttributesByDefault()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ATTRIBUTES_BY_DEFAULT, - enableAttributesByDefault); - String idPInitSSOEnabled = String.valueOf(serviceProviderDO.isIdPInitSSOEnabled()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_IDP_INIT_SSO_ENABLED, - idPInitSSOEnabled); - String idPInitSLOEnabled = String.valueOf(serviceProviderDO.isIdPInitSLOEnabled()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SLO_IDP_INIT_SLO_ENABLED, idPInitSLOEnabled); - if (serviceProviderDO.isIdPInitSLOEnabled() && serviceProviderDO.getIdpInitSLOReturnToURLList().size() > 0) { - resource.setProperty(IdentityRegistryResources.PROP_SAML_IDP_INIT_SLO_RETURN_URLS, - serviceProviderDO.getIdpInitSLOReturnToURLList()); - } - String enableEncryptedAssertion = String.valueOf(serviceProviderDO.isDoEnableEncryptedAssertion()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ENCRYPTED_ASSERTION, - enableEncryptedAssertion); - - String validateSignatureInRequests = String.valueOf(serviceProviderDO.isDoValidateSignatureInRequests()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_REQUESTS, - validateSignatureInRequests); - - String validateSignatureInArtifactResolve = - String.valueOf(serviceProviderDO.isDoValidateSignatureInArtifactResolve()); - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE, - validateSignatureInArtifactResolve); - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_QUALIFIER, serviceProviderDO - .getIssuerQualifier()); - } - if (StringUtils.isNotBlank(serviceProviderDO.getIdpEntityIDAlias())) { - resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_IDP_ENTITY_ID_ALIAS, serviceProviderDO - .getIdpEntityIDAlias()); - } - return resource; - } - - /** - * Get the issuer value by removing the qualifier. - * - * @param issuerWithQualifier issuer value saved in the registry. - * @return issuer value given as 'issuer' when configuring SAML SP. - */ - private String getIssuerWithoutQualifier(String issuerWithQualifier) { - - String issuerWithoutQualifier = StringUtils.substringBeforeLast(issuerWithQualifier, - IdentityRegistryResources.QUALIFIER_ID); - return issuerWithoutQualifier; - } - - /** - * Get the issuer value to be added to registry by appending the qualifier. - * - * @param issuer value given as 'issuer' when configuring SAML SP. - * @return issuer value with qualifier appended. - */ - private String getIssuerWithQualifier(String issuer, String qualifier) { - - String issuerWithQualifier = issuer + IdentityRegistryResources.QUALIFIER_ID + qualifier; - return issuerWithQualifier; - } + boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws IdentityException; /** * Update the service provider if it exists. @@ -483,373 +41,50 @@ private String getIssuerWithQualifier(String issuer, String qualifier) { * @throws IdentityException If an error occurs while updating the service provider. */ public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, String currentIssuer) - throws IdentityException { - - if (serviceProviderDO == null || serviceProviderDO.getIssuer() == null || - StringUtils.isBlank(serviceProviderDO.getIssuer())) { - throw new IdentityException("Issuer cannot be found in the provided arguments."); - } - - // If an issuer qualifier value is specified, it is appended to the end of the issuer value. - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - serviceProviderDO.setIssuer(getIssuerWithQualifier(serviceProviderDO.getIssuer(), - serviceProviderDO.getIssuerQualifier())); - } - - String currentPath = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(currentIssuer); - String newPath = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(serviceProviderDO.getIssuer()); + throws IdentityException; - boolean isIssuerUpdated = !StringUtils.equals(currentPath, newPath); - boolean isTransactionStarted = Transaction.isStarted(); - boolean isErrorOccurred = false; - try { - // Check if the updated issuer value already exists. - if (isIssuerUpdated && registry.resourceExists(newPath)) { - if (log.isDebugEnabled()) { - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - log.debug("SAML2 Service Provider already exists with the same issuer name " - + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier name " - + serviceProviderDO.getIssuerQualifier()); - } else { - log.debug("SAML2 Service Provider already exists with the same issuer name " - + serviceProviderDO.getIssuer()); - } - } - return false; - } - - Resource resource = createResource(serviceProviderDO); - if (!isTransactionStarted) { - registry.beginTransaction(); - } - // Delete the current resource if the issuer value is updated. - if (isIssuerUpdated) { - registry.delete(currentPath); - } - // Update the resource. - // If the issuer is updated, new resource will be created. - // If the issuer is not updated, existing resource will be updated. - registry.put(newPath, resource); - if (log.isDebugEnabled()) { - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " with issuer " - + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier " + - serviceProviderDO.getIssuerQualifier() + " is updated successfully."); - } else { - log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " is updated successfully."); - } - } - return true; - } catch (RegistryException e) { - isErrorOccurred = true; - String msg; - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - msg = "Error while updating SAML2 Service Provider for issuer: " + getIssuerWithoutQualifier - (serviceProviderDO.getIssuer()) + " and qualifier name " + serviceProviderDO - .getIssuerQualifier(); - } else { - msg = "Error while updating SAML2 Service Provider for issuer: " + serviceProviderDO.getIssuer(); - } - log.error(msg, e); - throw new IdentityException(msg, e); - } finally { - commitOrRollbackTransaction(isErrorOccurred); - } - } - - public SAMLSSOServiceProviderDO[] getServiceProviders() throws IdentityException { - List serviceProvidersList = new ArrayList<>(); - try { - if (registry.resourceExists(IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS)) { - Resource samlSSOServiceProvidersResource = registry.get(IdentityRegistryResources - .SAML_SSO_SERVICE_PROVIDERS); - if (samlSSOServiceProvidersResource instanceof Collection) { - Collection samlSSOServiceProvidersCollection = (Collection) samlSSOServiceProvidersResource; - String[] resources = samlSSOServiceProvidersCollection.getChildren(); - for (String resource : resources) { - getChildResources(resource, serviceProvidersList); - } - } - } - } catch (RegistryException e) { - log.error("Error reading Service Providers from Registry", e); - throw IdentityException.error("Error reading Service Providers from Registry", e); - } - return serviceProvidersList.toArray(new SAMLSSOServiceProviderDO[serviceProvidersList.size()]); - } + /** + * Get all the service providers. + * + * @return Array of service providers. + * @throws IdentityException Error occurred while retrieving the service providers from registry. + */ + SAMLSSOServiceProviderDO[] getServiceProviders() throws IdentityException; /** * Remove the service provider with the given name. + * * @return True if deletion success. * @param issuer Name of the SAML issuer. * @throws IdentityException Error occurred while removing the SAML service provider from registry. */ - public boolean removeServiceProvider(String issuer) throws IdentityException { - - if (issuer == null || StringUtils.isEmpty(issuer.trim())) { - throw new IllegalArgumentException("Trying to delete issuer \'" + issuer + "\'"); - } - - String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(issuer); - boolean isTransactionStarted = Transaction.isStarted(); - boolean isErrorOccurred = false; - try { - if (!registry.resourceExists(path)) { - if (log.isDebugEnabled()) { - log.debug("Registry resource does not exist for the path: " + path); - } - return false; - } - - // Since we are getting a global registry object, better to check whether this is a task inside already - // started transaction. - if (!isTransactionStarted) { - registry.beginTransaction(); - } - registry.delete(path); - return true; - } catch (RegistryException e) { - isErrorOccurred = true; - String msg = "Error removing the service provider from the registry with name: " + issuer; - log.error(msg, e); - throw IdentityException.error(msg, e); - } finally { - commitOrRollbackTransaction(isErrorOccurred); - } - } + boolean removeServiceProvider(String issuer) throws IdentityException; /** * Get the service provider. * - * @param issuer - * @return - * @throws IdentityException + * @param issuer Name of the SAML issuer. + * @return Service provider information object. + * @throws IdentityException Error occurred while retrieving the SAML service provider from registry. */ - public SAMLSSOServiceProviderDO getServiceProvider(String issuer) throws IdentityException { - - String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(issuer); - SAMLSSOServiceProviderDO serviceProviderDO = null; - - UserRegistry userRegistry = null; - String tenantDomain = null; - try { - userRegistry = (UserRegistry) registry; - tenantDomain = IdentityTenantUtil.getRealmService().getTenantManager().getDomain(userRegistry. - getTenantId()); - if (registry.resourceExists(path)) { - serviceProviderDO = resourceToObject(registry.get(path)); - - // Load the certificate stored in the database, if signature validation is enabled.. - if (serviceProviderDO.isDoValidateSignatureInRequests() || - serviceProviderDO.isDoValidateSignatureInArtifactResolve() || - serviceProviderDO.isDoEnableEncryptedAssertion()) { - Tenant tenant = new Tenant(); - tenant.setDomain(tenantDomain); - tenant.setId(userRegistry.getTenantId()); - - serviceProviderDO.setX509Certificate(getApplicationCertificate(serviceProviderDO, tenant)); - } - serviceProviderDO.setTenantDomain(tenantDomain); - } - } catch (RegistryException e) { - throw IdentityException.error("Error occurred while checking if resource path \'" + path + "\' exists in " + - "registry for tenant domain : " + tenantDomain, e); - } catch (UserStoreException e) { - throw IdentityException.error("Error occurred while getting tenant domain from tenant ID : " + - userRegistry.getTenantId(), e); - } catch (SQLException e) { - throw IdentityException.error(String.format("An error occurred while getting the " + - "application certificate id for validating the requests from the issuer '%s'", issuer), e); - } catch (CertificateRetrievingException e) { - throw IdentityException.error(String.format("An error occurred while getting the " + - "application certificate for validating the requests from the issuer '%s'", issuer), e); - } - return serviceProviderDO; - } + SAMLSSOServiceProviderDO getServiceProvider(String issuer) throws IdentityException; /** - * Returns the {@link java.security.cert.Certificate} which should used to validate the requests - * for the given service provider. + * Check whether the service provider exists. * - * @param serviceProviderDO - * @param tenant - * @return - * @throws SQLException - * @throws CertificateRetrievingException + * @param issuer Name of the SAML issuer. + * @return True if service provider exists. + * @throws IdentityException Error occurred while checking the existence of the SAML service provider. */ - private X509Certificate getApplicationCertificate(SAMLSSOServiceProviderDO serviceProviderDO, Tenant tenant) - throws SQLException, CertificateRetrievingException { - - // Check whether there is a certificate stored against the service provider (in the database) - int applicationCertificateId = getApplicationCertificateId(serviceProviderDO.getIssuer(), tenant.getId()); - - CertificateRetriever certificateRetriever; - String certificateIdentifier; - if (applicationCertificateId != -1) { - certificateRetriever = new DatabaseCertificateRetriever(); - certificateIdentifier = Integer.toString(applicationCertificateId); - } else { - certificateRetriever = new KeyStoreCertificateRetriever(); - certificateIdentifier = serviceProviderDO.getCertAlias(); - } - - return certificateRetriever.getCertificate(certificateIdentifier, tenant); - } + boolean isServiceProviderExists(String issuer) throws IdentityException; /** - * Returns the certificate reference ID for the given issuer (Service Provider) if there is one. + * Upload service Provider using metadata file. * - * @param issuer - * @return - * @throws SQLException - */ - private int getApplicationCertificateId(String issuer, int tenantId) throws SQLException { - - try { - String sqlStmt = isH2DB() ? QUERY_TO_GET_APPLICATION_CERTIFICATE_ID_H2 : - QUERY_TO_GET_APPLICATION_CERTIFICATE_ID; - try (Connection connection = IdentityDatabaseUtil.getDBConnection(false); - PreparedStatement statementToGetApplicationCertificate = - connection.prepareStatement(sqlStmt)) { - statementToGetApplicationCertificate.setString(1, CERTIFICATE_PROPERTY_NAME); - statementToGetApplicationCertificate.setString(2, issuer); - statementToGetApplicationCertificate.setInt(3, tenantId); - - try (ResultSet queryResults = statementToGetApplicationCertificate.executeQuery()) { - if (queryResults.next()) { - return queryResults.getInt(1); - } - } - } - return -1; - } catch (DataAccessException e) { - String errorMsg = "Error while retrieving application certificate data for issuer: " + issuer + - " and tenant Id: " + tenantId; - throw new SQLException(errorMsg, e); - } - } - - public boolean isServiceProviderExists(String issuer) throws IdentityException { - String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(issuer); - try { - return registry.resourceExists(path); - } catch (RegistryException e) { - throw IdentityException.error("Error occurred while checking if resource path \'" + path + "\' exists in " + - "registry"); - } - } - - private String encodePath(String path) { - String encodedStr = new String(Base64.encodeBase64(path.getBytes())); - return encodedStr.replace("=", ""); - } - - /** - * Upload service Provider using metadata file.. * @param serviceProviderDO Service provider information object. * @return True if upload success. * @throws IdentityException Error occurred while adding the information to registry. */ - public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws - IdentityException { - - if (serviceProviderDO == null || serviceProviderDO.getIssuer() == null) { - throw new IdentityException("Issuer cannot be found in the provided arguments."); - } - - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - serviceProviderDO.setIssuer(getIssuerWithQualifier(serviceProviderDO.getIssuer(), - serviceProviderDO.getIssuerQualifier())); - } - - if (serviceProviderDO.getDefaultAssertionConsumerUrl() == null) { - throw new IdentityException("No default assertion consumer URL provided for service provider :" + - serviceProviderDO.getIssuer()); - } - - String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(serviceProviderDO.getIssuer()); - - boolean isTransactionStarted = Transaction.isStarted(); - boolean isErrorOccurred = false; - try { - if (registry.resourceExists(path)) { - if (log.isDebugEnabled()) { - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - log.debug("SAML2 Service Provider already exists with the same issuer name " - + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier name " - + serviceProviderDO.getIssuerQualifier()); - } else { - log.debug("SAML2 Service Provider already exists with the same issuer name " - + serviceProviderDO.getIssuer()); - } - } - throw IdentityException.error("A Service Provider already exists."); - } - - if (!isTransactionStarted) { - registry.beginTransaction(); - } - - Resource resource = createResource(serviceProviderDO); - registry.put(path, resource); - if (log.isDebugEnabled()) { - if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { - log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " with issuer " - + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier " + - serviceProviderDO.getIssuerQualifier() + " is added successfully."); - } else { - log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " is added successfully."); - } - } - return serviceProviderDO; - } catch (RegistryException e) { - isErrorOccurred = true; - throw IdentityException.error("Error while adding Service Provider.", e); - } finally { - commitOrRollbackTransaction(isErrorOccurred); - } - } - - /** - * Commit or rollback the registry operation depends on the error condition. - * @param isErrorOccurred Identifier for error transactions. - * @throws IdentityException Error while committing or running rollback on the transaction. - */ - private void commitOrRollbackTransaction(boolean isErrorOccurred) throws IdentityException { - - try { - // Rollback the transaction if there is an error, Otherwise try to commit. - if (isErrorOccurred) { - registry.rollbackTransaction(); - } else { - registry.commitTransaction(); - } - } catch (RegistryException ex) { - throw new IdentityException("Error occurred while trying to commit or rollback the registry operation.", ex); - } - } - - /** - * This helps to find resources in a recursive manner. - * - * @param parentResource parent resource Name. - * @param serviceProviderList child resource list. - * @throws RegistryException - */ - private void getChildResources(String parentResource, List - serviceProviderList) throws RegistryException { - - if (registry.resourceExists(parentResource)) { - Resource resource = registry.get(parentResource); - if (resource instanceof Collection) { - Collection collection = (Collection) resource; - String[] resources = collection.getChildren(); - for (String res : resources) { - getChildResources(res, serviceProviderList); - } - } else { - serviceProviderList.add(resourceToObject(resource)); - } - } - } + SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws + IdentityException; } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderRegistryDAOImpl.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderRegistryDAOImpl.java new file mode 100644 index 000000000000..08ac0b769c89 --- /dev/null +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderRegistryDAOImpl.java @@ -0,0 +1,857 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. 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.identity.core.dao; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; +import org.wso2.carbon.identity.base.IdentityException; +import org.wso2.carbon.identity.core.CertificateRetriever; +import org.wso2.carbon.identity.core.CertificateRetrievingException; +import org.wso2.carbon.identity.core.DatabaseCertificateRetriever; +import org.wso2.carbon.identity.core.IdentityRegistryResources; +import org.wso2.carbon.identity.core.KeyStoreCertificateRetriever; +import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO; +import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.registry.core.Collection; +import org.wso2.carbon.registry.core.Registry; +import org.wso2.carbon.registry.core.Resource; +import org.wso2.carbon.registry.core.exceptions.RegistryException; +import org.wso2.carbon.registry.core.jdbc.utils.Transaction; +import org.wso2.carbon.registry.core.session.UserRegistry; +import org.wso2.carbon.user.api.Tenant; +import org.wso2.carbon.user.api.UserStoreException; + +import java.security.cert.X509Certificate; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import static org.wso2.carbon.identity.core.util.JdbcUtils.isH2DB; + +public class SAMLSSOServiceProviderRegistryDAOImpl extends AbstractDAO + implements SAMLSSOServiceProviderDAO { + private static final String CERTIFICATE_PROPERTY_NAME = "CERTIFICATE"; + private static final String QUERY_TO_GET_APPLICATION_CERTIFICATE_ID = "SELECT " + + "META.VALUE FROM SP_INBOUND_AUTH INBOUND, SP_APP SP, SP_METADATA META WHERE SP.ID = INBOUND.APP_ID AND " + + "SP.ID = META.SP_ID AND META.NAME = ? AND INBOUND.INBOUND_AUTH_KEY = ? AND META.TENANT_ID = ?"; + + private static final String QUERY_TO_GET_APPLICATION_CERTIFICATE_ID_H2 = "SELECT " + + "META.`VALUE` FROM SP_INBOUND_AUTH INBOUND, SP_APP SP, SP_METADATA META WHERE SP.ID = INBOUND.APP_ID AND " + + "SP.ID = META.SP_ID AND META.NAME = ? AND INBOUND.INBOUND_AUTH_KEY = ? AND META.TENANT_ID = ?"; + + private static Log log = LogFactory.getLog(SAMLSSOServiceProviderDAO.class); + + public SAMLSSOServiceProviderRegistryDAOImpl(Registry registry) { + this.registry = registry; + } + + protected SAMLSSOServiceProviderDO resourceToObject(Resource resource) { + SAMLSSOServiceProviderDO serviceProviderDO = new SAMLSSOServiceProviderDO(); + serviceProviderDO.setIssuer(resource + .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER)); + serviceProviderDO.setAssertionConsumerUrls(resource.getPropertyValues( + IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_CONS_URLS)); + serviceProviderDO.setDefaultAssertionConsumerUrl(resource.getProperty( + IdentityRegistryResources.PROP_DEFAULT_SAML_SSO_ASSERTION_CONS_URL)); + serviceProviderDO.setCertAlias(resource + .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_CERT_ALIAS)); + + if (StringUtils.isNotEmpty(resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_SIGNING_ALGORITHM))) { + serviceProviderDO.setSigningAlgorithmUri(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SSO_SIGNING_ALGORITHM)); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED) != + null) { + serviceProviderDO.setAssertionQueryRequestProfileEnabled(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED).trim())); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES) != + null) { + serviceProviderDO.setSupportedAssertionQueryRequestTypes(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES).trim()); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_SAML2_ARTIFACT_BINDING) != + null) { + serviceProviderDO.setEnableSAML2ArtifactBinding(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_ENABLE_SAML2_ARTIFACT_BINDING).trim())); + } + + if (StringUtils.isNotEmpty(resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DIGEST_ALGORITHM))) { + serviceProviderDO.setDigestAlgorithmUri(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SSO_DIGEST_ALGORITHM)); + } + + if (StringUtils.isNotEmpty(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SSO_ASSERTION_ENCRYPTION_ALGORITHM))) { + serviceProviderDO.setAssertionEncryptionAlgorithmUri(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SSO_ASSERTION_ENCRYPTION_ALGORITHM)); + } + + if (StringUtils.isNotEmpty(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SSO_KEY_ENCRYPTION_ALGORITHM))) { + serviceProviderDO.setKeyEncryptionAlgorithmUri(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SSO_KEY_ENCRYPTION_ALGORITHM)); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SINGLE_LOGOUT) != null) { + serviceProviderDO.setDoSingleLogout(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_DO_SINGLE_LOGOUT).trim())); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_NAMEID_FORMAT) != null) { + serviceProviderDO.setNameIDFormat(resource. + getProperty(IdentityRegistryResources.PROP_SAML_SSO_NAMEID_FORMAT)); + } + + if (resource + .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_NAMEID_CLAIMURI) != null) { + if (Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_ENABLE_NAMEID_CLAIMURI).trim())) { + serviceProviderDO.setNameIdClaimUri(resource. + getProperty(IdentityRegistryResources.PROP_SAML_SSO_NAMEID_CLAIMURI)); + } + } + + serviceProviderDO.setLoginPageURL(resource. + getProperty(IdentityRegistryResources.PROP_SAML_SSO_LOGIN_PAGE_URL)); + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_RESPONSE) != null) { + serviceProviderDO.setDoSignResponse(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_RESPONSE).trim())); + } + + if (serviceProviderDO.isDoSingleLogout()) { + serviceProviderDO.setSloResponseURL(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SLO_RESPONSE_URL)); + serviceProviderDO.setSloRequestURL(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SLO_REQUEST_URL)); + // Check front channel logout enable. + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_FRONT_CHANNEL_LOGOUT) != null) { + serviceProviderDO.setDoFrontChannelLogout(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_DO_FRONT_CHANNEL_LOGOUT).trim())); + if (serviceProviderDO.isDoFrontChannelLogout()) { + if (resource.getProperty(IdentityRegistryResources. + PROP_SAML_SSO_FRONT_CHANNEL_LOGOUT_BINDING) != null) { + serviceProviderDO.setFrontChannelLogoutBinding(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_FRONT_CHANNEL_LOGOUT_BINDING)); + } else { + // Default is redirect-binding. + serviceProviderDO.setFrontChannelLogoutBinding(IdentityRegistryResources + .DEFAULT_FRONT_CHANNEL_LOGOUT_BINDING); + } + + } + } + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_ASSERTIONS) != null) { + serviceProviderDO.setDoSignAssertions(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_ASSERTIONS).trim())); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_ENABLE_ECP) != null) { + serviceProviderDO.setSamlECP(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_ENABLE_ECP).trim())); + } + + if (resource + .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ATTRIB_CONSUMING_SERVICE_INDEX) != null) { + serviceProviderDO + .setAttributeConsumingServiceIndex(resource + .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ATTRIB_CONSUMING_SERVICE_INDEX)); + } else { + // Specific DB's (like oracle) returns empty strings as null. + serviceProviderDO.setAttributeConsumingServiceIndex(""); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_CLAIMS) != null) { + serviceProviderDO.setRequestedClaims(resource + .getPropertyValues(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_CLAIMS)); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_AUDIENCES) != null) { + serviceProviderDO.setRequestedAudiences(resource + .getPropertyValues(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_AUDIENCES)); + } + + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_RECIPIENTS) != null) { + serviceProviderDO.setRequestedRecipients(resource + .getPropertyValues(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_RECIPIENTS)); + } + + if (resource + .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ATTRIBUTES_BY_DEFAULT) != null) { + String enableAttrByDefault = resource + .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ATTRIBUTES_BY_DEFAULT); + serviceProviderDO.setEnableAttributesByDefault(Boolean.valueOf(enableAttrByDefault)); + } + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_IDP_INIT_SSO_ENABLED) != null) { + serviceProviderDO.setIdPInitSSOEnabled(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_IDP_INIT_SSO_ENABLED).trim())); + } + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SLO_IDP_INIT_SLO_ENABLED) != null) { + serviceProviderDO.setIdPInitSLOEnabled(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SLO_IDP_INIT_SLO_ENABLED).trim())); + if (serviceProviderDO.isIdPInitSLOEnabled() && resource.getProperty( + IdentityRegistryResources.PROP_SAML_IDP_INIT_SLO_RETURN_URLS) != null) { + serviceProviderDO.setIdpInitSLOReturnToURLs(resource.getPropertyValues( + IdentityRegistryResources.PROP_SAML_IDP_INIT_SLO_RETURN_URLS)); + } + } + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ENCRYPTED_ASSERTION) != null) { + serviceProviderDO.setDoEnableEncryptedAssertion(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ENCRYPTED_ASSERTION).trim())); + } + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_REQUESTS) != null) { + serviceProviderDO.setDoValidateSignatureInRequests(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_REQUESTS).trim())); + } + if (resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE) != null) { + serviceProviderDO.setDoValidateSignatureInArtifactResolve(Boolean.valueOf(resource.getProperty( + IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE).trim())); + } + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_QUALIFIER) != null) { + serviceProviderDO.setIssuerQualifier(resource + .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_QUALIFIER)); + } + if (resource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_IDP_ENTITY_ID_ALIAS) != null) { + serviceProviderDO.setIdpEntityIDAlias(resource.getProperty(IdentityRegistryResources + .PROP_SAML_SSO_IDP_ENTITY_ID_ALIAS)); + } + return serviceProviderDO; + } + + /** + * Add the service provider information to the registry. + * @param serviceProviderDO Service provider information object. + * @return True if addition successful. + * @throws IdentityException Error while persisting to the registry. + */ + public boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws IdentityException { + + if (serviceProviderDO == null || serviceProviderDO.getIssuer() == null || + StringUtils.isBlank(serviceProviderDO.getIssuer())) { + throw new IdentityException("Issuer cannot be found in the provided arguments."); + } + + // If an issuer qualifier value is specified, it is appended to the end of the issuer value. + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + serviceProviderDO.setIssuer(getIssuerWithQualifier(serviceProviderDO.getIssuer(), + serviceProviderDO.getIssuerQualifier())); + } + + String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(serviceProviderDO.getIssuer()); + + boolean isTransactionStarted = Transaction.isStarted(); + boolean isErrorOccurred = false; + try { + if (registry.resourceExists(path)) { + if (log.isDebugEnabled()) { + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + log.debug("SAML2 Service Provider already exists with the same issuer name " + + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier name " + + serviceProviderDO.getIssuerQualifier()); + } else { + log.debug("SAML2 Service Provider already exists with the same issuer name " + + serviceProviderDO.getIssuer()); + } + } + return false; + } + + Resource resource = createResource(serviceProviderDO); + if (!isTransactionStarted) { + registry.beginTransaction(); + } + registry.put(path, resource); + if (log.isDebugEnabled()) { + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " with issuer " + + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier " + + serviceProviderDO.getIssuerQualifier() + " is added successfully."); + } else { + log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " is added successfully."); + } + } + return true; + } catch (RegistryException e) { + isErrorOccurred = true; + String msg; + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + msg = "Error while adding SAML2 Service Provider for issuer: " + getIssuerWithoutQualifier + (serviceProviderDO.getIssuer()) + " and qualifier name " + serviceProviderDO + .getIssuerQualifier(); + } else { + msg = "Error while adding SAML2 Service Provider for issuer: " + serviceProviderDO.getIssuer(); + } + log.error(msg, e); + throw IdentityException.error(msg, e); + } finally { + commitOrRollbackTransaction(isErrorOccurred); + } + } + + private Resource createResource(SAMLSSOServiceProviderDO serviceProviderDO) throws RegistryException { + Resource resource; + resource = registry.newResource(); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER, + serviceProviderDO.getIssuer()); + resource.setProperty(IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_CONS_URLS, + serviceProviderDO.getAssertionConsumerUrlList()); + resource.addProperty(IdentityRegistryResources.PROP_DEFAULT_SAML_SSO_ASSERTION_CONS_URL, + serviceProviderDO.getDefaultAssertionConsumerUrl()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_CERT_ALIAS, + serviceProviderDO.getCertAlias()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_LOGIN_PAGE_URL, + serviceProviderDO.getLoginPageURL()); + resource.addProperty( + IdentityRegistryResources.PROP_SAML_SSO_NAMEID_FORMAT, + serviceProviderDO.getNameIDFormat()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_SIGNING_ALGORITHM, serviceProviderDO + .getSigningAlgorithmUri()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DIGEST_ALGORITHM, serviceProviderDO + .getDigestAlgorithmUri()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_ENCRYPTION_ALGORITHM, serviceProviderDO + .getAssertionEncryptionAlgorithmUri()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_KEY_ENCRYPTION_ALGORITHM, serviceProviderDO + .getKeyEncryptionAlgorithmUri()); + if (serviceProviderDO.getNameIdClaimUri() != null + && serviceProviderDO.getNameIdClaimUri().trim().length() > 0) { + resource.addProperty( + IdentityRegistryResources.PROP_SAML_SSO_ENABLE_NAMEID_CLAIMURI, + "true"); + resource.addProperty( + IdentityRegistryResources.PROP_SAML_SSO_NAMEID_CLAIMURI, + serviceProviderDO.getNameIdClaimUri()); + } else { + resource.addProperty( + IdentityRegistryResources.PROP_SAML_SSO_ENABLE_NAMEID_CLAIMURI, + "false"); + } + + String doSingleLogout = String.valueOf(serviceProviderDO.isDoSingleLogout()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SINGLE_LOGOUT, doSingleLogout); + if (serviceProviderDO.isDoSingleLogout()) { + if (StringUtils.isNotBlank(serviceProviderDO.getSloResponseURL())) { + resource.addProperty(IdentityRegistryResources.PROP_SAML_SLO_RESPONSE_URL, + serviceProviderDO.getSloResponseURL()); + } + if (StringUtils.isNotBlank(serviceProviderDO.getSloRequestURL())) { + resource.addProperty(IdentityRegistryResources.PROP_SAML_SLO_REQUEST_URL, + serviceProviderDO.getSloRequestURL()); + } + // Create doFrontChannelLogout property in the registry. + String doFrontChannelLogout = String.valueOf(serviceProviderDO.isDoFrontChannelLogout()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_FRONT_CHANNEL_LOGOUT, doFrontChannelLogout); + if (serviceProviderDO.isDoFrontChannelLogout()) { + // Create frontChannelLogoutMethod property in the registry. + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_FRONT_CHANNEL_LOGOUT_BINDING, + serviceProviderDO.getFrontChannelLogoutBinding()); + } + } + + String doSignResponse = String.valueOf(serviceProviderDO.isDoSignResponse()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_RESPONSE, + doSignResponse); + String isAssertionQueryRequestProfileEnabled = String.valueOf(serviceProviderDO + .isAssertionQueryRequestProfileEnabled()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED, + isAssertionQueryRequestProfileEnabled); + String supportedAssertionQueryRequestTypes = serviceProviderDO.getSupportedAssertionQueryRequestTypes(); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES, + supportedAssertionQueryRequestTypes); + String isEnableSAML2ArtifactBinding = String.valueOf(serviceProviderDO + .isEnableSAML2ArtifactBinding()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_SAML2_ARTIFACT_BINDING, + isEnableSAML2ArtifactBinding); + String doSignAssertions = String.valueOf(serviceProviderDO.isDoSignAssertions()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_DO_SIGN_ASSERTIONS, + doSignAssertions); + String isSamlECP = String.valueOf(serviceProviderDO.isSamlECP()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_ENABLE_ECP, + isSamlECP); + if (CollectionUtils.isNotEmpty(serviceProviderDO.getRequestedClaimsList())) { + resource.setProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_CLAIMS, + serviceProviderDO.getRequestedClaimsList()); + } + if (serviceProviderDO.getAttributeConsumingServiceIndex() != null) { + resource.addProperty( + IdentityRegistryResources.PROP_SAML_SSO_ATTRIB_CONSUMING_SERVICE_INDEX, + serviceProviderDO.getAttributeConsumingServiceIndex()); + } + if (CollectionUtils.isNotEmpty(serviceProviderDO.getRequestedAudiencesList())) { + resource.setProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_AUDIENCES, + serviceProviderDO.getRequestedAudiencesList()); + } + if (CollectionUtils.isNotEmpty(serviceProviderDO.getRequestedRecipientsList())) { + resource.setProperty(IdentityRegistryResources.PROP_SAML_SSO_REQUESTED_RECIPIENTS, + serviceProviderDO.getRequestedRecipientsList()); + } + + String enableAttributesByDefault = String.valueOf(serviceProviderDO.isEnableAttributesByDefault()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ATTRIBUTES_BY_DEFAULT, + enableAttributesByDefault); + String idPInitSSOEnabled = String.valueOf(serviceProviderDO.isIdPInitSSOEnabled()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_IDP_INIT_SSO_ENABLED, + idPInitSSOEnabled); + String idPInitSLOEnabled = String.valueOf(serviceProviderDO.isIdPInitSLOEnabled()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SLO_IDP_INIT_SLO_ENABLED, idPInitSLOEnabled); + if (serviceProviderDO.isIdPInitSLOEnabled() && serviceProviderDO.getIdpInitSLOReturnToURLList().size() > 0) { + resource.setProperty(IdentityRegistryResources.PROP_SAML_IDP_INIT_SLO_RETURN_URLS, + serviceProviderDO.getIdpInitSLOReturnToURLList()); + } + String enableEncryptedAssertion = String.valueOf(serviceProviderDO.isDoEnableEncryptedAssertion()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ENABLE_ENCRYPTED_ASSERTION, + enableEncryptedAssertion); + + String validateSignatureInRequests = String.valueOf(serviceProviderDO.isDoValidateSignatureInRequests()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_REQUESTS, + validateSignatureInRequests); + + String validateSignatureInArtifactResolve = + String.valueOf(serviceProviderDO.isDoValidateSignatureInArtifactResolve()); + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE, + validateSignatureInArtifactResolve); + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER_QUALIFIER, serviceProviderDO + .getIssuerQualifier()); + } + if (StringUtils.isNotBlank(serviceProviderDO.getIdpEntityIDAlias())) { + resource.addProperty(IdentityRegistryResources.PROP_SAML_SSO_IDP_ENTITY_ID_ALIAS, serviceProviderDO + .getIdpEntityIDAlias()); + } + return resource; + } + + /** + * Get the issuer value by removing the qualifier. + * + * @param issuerWithQualifier issuer value saved in the registry. + * @return issuer value given as 'issuer' when configuring SAML SP. + */ + private String getIssuerWithoutQualifier(String issuerWithQualifier) { + + String issuerWithoutQualifier = StringUtils.substringBeforeLast(issuerWithQualifier, + IdentityRegistryResources.QUALIFIER_ID); + return issuerWithoutQualifier; + } + + /** + * Get the issuer value to be added to registry by appending the qualifier. + * + * @param issuer value given as 'issuer' when configuring SAML SP. + * @return issuer value with qualifier appended. + */ + private String getIssuerWithQualifier(String issuer, String qualifier) { + + String issuerWithQualifier = issuer + IdentityRegistryResources.QUALIFIER_ID + qualifier; + return issuerWithQualifier; + } + + /** + * Update the service provider if it exists. + * + * @param serviceProviderDO Service provider to be updated. + * @param currentIssuer Issuer of the service provider before the update. + * @return True if the update is successful. + * @throws IdentityException If an error occurs while updating the service provider. + */ + public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, String currentIssuer) + throws IdentityException { + + if (serviceProviderDO == null || serviceProviderDO.getIssuer() == null || + StringUtils.isBlank(serviceProviderDO.getIssuer())) { + throw new IdentityException("Issuer cannot be found in the provided arguments."); + } + + // If an issuer qualifier value is specified, it is appended to the end of the issuer value. + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + serviceProviderDO.setIssuer(getIssuerWithQualifier(serviceProviderDO.getIssuer(), + serviceProviderDO.getIssuerQualifier())); + } + + String currentPath = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(currentIssuer); + String newPath = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(serviceProviderDO.getIssuer()); + + boolean isIssuerUpdated = !StringUtils.equals(currentPath, newPath); + boolean isTransactionStarted = Transaction.isStarted(); + boolean isErrorOccurred = false; + try { + // Check if the updated issuer value already exists. + if (isIssuerUpdated && registry.resourceExists(newPath)) { + if (log.isDebugEnabled()) { + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + log.debug("SAML2 Service Provider already exists with the same issuer name " + + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier name " + + serviceProviderDO.getIssuerQualifier()); + } else { + log.debug("SAML2 Service Provider already exists with the same issuer name " + + serviceProviderDO.getIssuer()); + } + } + return false; + } + + Resource resource = createResource(serviceProviderDO); + if (!isTransactionStarted) { + registry.beginTransaction(); + } + // Delete the current resource if the issuer value is updated. + if (isIssuerUpdated) { + registry.delete(currentPath); + } + // Update the resource. + // If the issuer is updated, new resource will be created. + // If the issuer is not updated, existing resource will be updated. + registry.put(newPath, resource); + if (log.isDebugEnabled()) { + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " with issuer " + + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier " + + serviceProviderDO.getIssuerQualifier() + " is updated successfully."); + } else { + log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " is updated successfully."); + } + } + return true; + } catch (RegistryException e) { + isErrorOccurred = true; + String msg; + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + msg = "Error while updating SAML2 Service Provider for issuer: " + getIssuerWithoutQualifier + (serviceProviderDO.getIssuer()) + " and qualifier name " + serviceProviderDO + .getIssuerQualifier(); + } else { + msg = "Error while updating SAML2 Service Provider for issuer: " + serviceProviderDO.getIssuer(); + } + log.error(msg, e); + throw new IdentityException(msg, e); + } finally { + commitOrRollbackTransaction(isErrorOccurred); + } + } + + public SAMLSSOServiceProviderDO[] getServiceProviders() throws IdentityException { + List serviceProvidersList = new ArrayList<>(); + try { + if (registry.resourceExists(IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS)) { + Resource samlSSOServiceProvidersResource = registry.get(IdentityRegistryResources + .SAML_SSO_SERVICE_PROVIDERS); + if (samlSSOServiceProvidersResource instanceof Collection) { + Collection samlSSOServiceProvidersCollection = (Collection) samlSSOServiceProvidersResource; + String[] resources = samlSSOServiceProvidersCollection.getChildren(); + for (String resource : resources) { + getChildResources(resource, serviceProvidersList); + } + } + } + } catch (RegistryException e) { + log.error("Error reading Service Providers from Registry", e); + throw IdentityException.error("Error reading Service Providers from Registry", e); + } + return serviceProvidersList.toArray(new SAMLSSOServiceProviderDO[serviceProvidersList.size()]); + } + + /** + * Remove the service provider with the given name. + * @return True if deletion success. + * @param issuer Name of the SAML issuer. + * @throws IdentityException Error occurred while removing the SAML service provider from registry. + */ + public boolean removeServiceProvider(String issuer) throws IdentityException { + + if (issuer == null || StringUtils.isEmpty(issuer.trim())) { + throw new IllegalArgumentException("Trying to delete issuer \'" + issuer + "\'"); + } + + String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(issuer); + boolean isTransactionStarted = Transaction.isStarted(); + boolean isErrorOccurred = false; + try { + if (!registry.resourceExists(path)) { + if (log.isDebugEnabled()) { + log.debug("Registry resource does not exist for the path: " + path); + } + return false; + } + + // Since we are getting a global registry object, better to check whether this is a task inside already + // started transaction. + if (!isTransactionStarted) { + registry.beginTransaction(); + } + registry.delete(path); + return true; + } catch (RegistryException e) { + isErrorOccurred = true; + String msg = "Error removing the service provider from the registry with name: " + issuer; + log.error(msg, e); + throw IdentityException.error(msg, e); + } finally { + commitOrRollbackTransaction(isErrorOccurred); + } + } + + /** + * Get the service provider. + * + * @param issuer + * @return + * @throws IdentityException + */ + public SAMLSSOServiceProviderDO getServiceProvider(String issuer) throws IdentityException { + + String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(issuer); + SAMLSSOServiceProviderDO serviceProviderDO = null; + + UserRegistry userRegistry = null; + String tenantDomain = null; + try { + userRegistry = (UserRegistry) registry; + tenantDomain = IdentityTenantUtil.getRealmService().getTenantManager().getDomain(userRegistry. + getTenantId()); + if (registry.resourceExists(path)) { + serviceProviderDO = resourceToObject(registry.get(path)); + + // Load the certificate stored in the database, if signature validation is enabled.. + if (serviceProviderDO.isDoValidateSignatureInRequests() || + serviceProviderDO.isDoValidateSignatureInArtifactResolve() || + serviceProviderDO.isDoEnableEncryptedAssertion()) { + Tenant tenant = new Tenant(); + tenant.setDomain(tenantDomain); + tenant.setId(userRegistry.getTenantId()); + + serviceProviderDO.setX509Certificate(getApplicationCertificate(serviceProviderDO, tenant)); + } + serviceProviderDO.setTenantDomain(tenantDomain); + } + } catch (RegistryException e) { + throw IdentityException.error("Error occurred while checking if resource path \'" + path + "\' exists in " + + "registry for tenant domain : " + tenantDomain, e); + } catch (UserStoreException e) { + throw IdentityException.error("Error occurred while getting tenant domain from tenant ID : " + + userRegistry.getTenantId(), e); + } catch (SQLException e) { + throw IdentityException.error(String.format("An error occurred while getting the " + + "application certificate id for validating the requests from the issuer '%s'", issuer), e); + } catch (CertificateRetrievingException e) { + throw IdentityException.error(String.format("An error occurred while getting the " + + "application certificate for validating the requests from the issuer '%s'", issuer), e); + } + return serviceProviderDO; + } + + /** + * Returns the {@link java.security.cert.Certificate} which should used to validate the requests + * for the given service provider. + * + * @param serviceProviderDO + * @param tenant + * @return + * @throws SQLException + * @throws CertificateRetrievingException + */ + private X509Certificate getApplicationCertificate(SAMLSSOServiceProviderDO serviceProviderDO, Tenant tenant) + throws SQLException, CertificateRetrievingException { + + // Check whether there is a certificate stored against the service provider (in the database) + int applicationCertificateId = getApplicationCertificateId(serviceProviderDO.getIssuer(), tenant.getId()); + + CertificateRetriever certificateRetriever; + String certificateIdentifier; + if (applicationCertificateId != -1) { + certificateRetriever = new DatabaseCertificateRetriever(); + certificateIdentifier = Integer.toString(applicationCertificateId); + } else { + certificateRetriever = new KeyStoreCertificateRetriever(); + certificateIdentifier = serviceProviderDO.getCertAlias(); + } + + return certificateRetriever.getCertificate(certificateIdentifier, tenant); + } + + /** + * Returns the certificate reference ID for the given issuer (Service Provider) if there is one. + * + * @param issuer + * @return + * @throws SQLException + */ + private int getApplicationCertificateId(String issuer, int tenantId) throws SQLException { + + try { + String sqlStmt = isH2DB() ? QUERY_TO_GET_APPLICATION_CERTIFICATE_ID_H2 : + QUERY_TO_GET_APPLICATION_CERTIFICATE_ID; + try (Connection connection = IdentityDatabaseUtil.getDBConnection(false); + PreparedStatement statementToGetApplicationCertificate = + connection.prepareStatement(sqlStmt)) { + statementToGetApplicationCertificate.setString(1, CERTIFICATE_PROPERTY_NAME); + statementToGetApplicationCertificate.setString(2, issuer); + statementToGetApplicationCertificate.setInt(3, tenantId); + + try (ResultSet queryResults = statementToGetApplicationCertificate.executeQuery()) { + if (queryResults.next()) { + return queryResults.getInt(1); + } + } + } + return -1; + } catch (DataAccessException e) { + String errorMsg = "Error while retrieving application certificate data for issuer: " + issuer + + " and tenant Id: " + tenantId; + throw new SQLException(errorMsg, e); + } + } + + public boolean isServiceProviderExists(String issuer) throws IdentityException { + String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(issuer); + try { + return registry.resourceExists(path); + } catch (RegistryException e) { + throw IdentityException.error("Error occurred while checking if resource path \'" + path + "\' exists in " + + "registry"); + } + } + + private String encodePath(String path) { + String encodedStr = new String(Base64.encodeBase64(path.getBytes())); + return encodedStr.replace("=", ""); + } + + /** + * Upload service Provider using metadata file.. + * @param serviceProviderDO Service provider information object. + * @return True if upload success. + * @throws IdentityException Error occurred while adding the information to registry. + */ + public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws + IdentityException { + + if (serviceProviderDO == null || serviceProviderDO.getIssuer() == null) { + throw new IdentityException("Issuer cannot be found in the provided arguments."); + } + + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + serviceProviderDO.setIssuer(getIssuerWithQualifier(serviceProviderDO.getIssuer(), + serviceProviderDO.getIssuerQualifier())); + } + + if (serviceProviderDO.getDefaultAssertionConsumerUrl() == null) { + throw new IdentityException("No default assertion consumer URL provided for service provider :" + + serviceProviderDO.getIssuer()); + } + + String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(serviceProviderDO.getIssuer()); + + boolean isTransactionStarted = Transaction.isStarted(); + boolean isErrorOccurred = false; + try { + if (registry.resourceExists(path)) { + if (log.isDebugEnabled()) { + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + log.debug("SAML2 Service Provider already exists with the same issuer name " + + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier name " + + serviceProviderDO.getIssuerQualifier()); + } else { + log.debug("SAML2 Service Provider already exists with the same issuer name " + + serviceProviderDO.getIssuer()); + } + } + throw IdentityException.error("A Service Provider already exists."); + } + + if (!isTransactionStarted) { + registry.beginTransaction(); + } + + Resource resource = createResource(serviceProviderDO); + registry.put(path, resource); + if (log.isDebugEnabled()) { + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " with issuer " + + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + " and qualifier " + + serviceProviderDO.getIssuerQualifier() + " is added successfully."); + } else { + log.debug("SAML2 Service Provider " + serviceProviderDO.getIssuer() + " is added successfully."); + } + } + return serviceProviderDO; + } catch (RegistryException e) { + isErrorOccurred = true; + throw IdentityException.error("Error while adding Service Provider.", e); + } finally { + commitOrRollbackTransaction(isErrorOccurred); + } + } + + /** + * Commit or rollback the registry operation depends on the error condition. + * @param isErrorOccurred Identifier for error transactions. + * @throws IdentityException Error while committing or running rollback on the transaction. + */ + private void commitOrRollbackTransaction(boolean isErrorOccurred) throws IdentityException { + + try { + // Rollback the transaction if there is an error, Otherwise try to commit. + if (isErrorOccurred) { + registry.rollbackTransaction(); + } else { + registry.commitTransaction(); + } + } catch (RegistryException ex) { + throw new IdentityException("Error occurred while trying to commit or rollback the registry operation.", ex); + } + } + + /** + * This helps to find resources in a recursive manner. + * + * @param parentResource parent resource Name. + * @param serviceProviderList child resource list. + * @throws RegistryException + */ + private void getChildResources(String parentResource, List + serviceProviderList) throws RegistryException { + + if (registry.resourceExists(parentResource)) { + Resource resource = registry.get(parentResource); + if (resource instanceof Collection) { + Collection collection = (Collection) resource; + String[] resources = collection.getChildren(); + for (String res : resources) { + getChildResources(res, serviceProviderList); + } + } else { + serviceProviderList.add(resourceToObject(resource)); + } + } + } +} diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/persistence/IdentityPersistenceManager.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/persistence/IdentityPersistenceManager.java index e1d8b461b967..93234f57d6b6 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/persistence/IdentityPersistenceManager.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/persistence/IdentityPersistenceManager.java @@ -22,6 +22,7 @@ import org.wso2.carbon.identity.core.dao.OpenIDUserDAO; import org.wso2.carbon.identity.core.dao.ParameterDAO; import org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderDAO; +import org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderRegistryDAOImpl; import org.wso2.carbon.identity.core.dao.XMPPSettingsDAO; import org.wso2.carbon.identity.core.model.OpenIDAdminDO; import org.wso2.carbon.identity.core.model.OpenIDUserDO; @@ -235,7 +236,7 @@ public void removeOpenIDSignUp(Registry registry, UserRealm realm, String openID */ public boolean addServiceProvider(Registry registry, SAMLSSOServiceProviderDO serviceProviderDO) throws IdentityException { - SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderDAO(registry); + SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderRegistryDAOImpl(registry); return serviceProviderDAO.addServiceProvider(serviceProviderDO); } /** @@ -246,7 +247,7 @@ public boolean addServiceProvider(Registry registry, SAMLSSOServiceProviderDO se * @throws IdentityException */ public SAMLSSOServiceProviderDO uploadServiceProvider(Registry registry, SAMLSSOServiceProviderDO samlssoServiceProviderDO) throws IdentityException { - SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderDAO(registry); + SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderRegistryDAOImpl(registry); return serviceProviderDAO.uploadServiceProvider(samlssoServiceProviderDO); } @@ -258,23 +259,23 @@ public SAMLSSOServiceProviderDO uploadServiceProvider(Registry registry, SAMLSSO */ public SAMLSSOServiceProviderDO[] getServiceProviders(Registry registry) throws IdentityException { - SAMLSSOServiceProviderDAO serviceProviderDOA = new SAMLSSOServiceProviderDAO(registry); + SAMLSSOServiceProviderDAO serviceProviderDOA = new SAMLSSOServiceProviderRegistryDAOImpl(registry); return serviceProviderDOA.getServiceProviders(); } public boolean removeServiceProvider(Registry registry, String issuer) throws IdentityException { - SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderDAO(registry); + SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderRegistryDAOImpl(registry); return serviceProviderDAO.removeServiceProvider(issuer); } public SAMLSSOServiceProviderDO getServiceProvider(Registry registry, String issuer) throws IdentityException { - SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderDAO(registry); + SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderRegistryDAOImpl(registry); return serviceProviderDAO.getServiceProvider(issuer); } public boolean isServiceProviderExists(Registry registry, String issuer) throws IdentityException { - SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderDAO(registry); + SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderRegistryDAOImpl(registry); return serviceProviderDAO.isServiceProviderExists(issuer); } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAOTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAOTest.java index 928429f47d92..1e68820389ca 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAOTest.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAOTest.java @@ -1,19 +1,19 @@ /* - * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) (2007-2023), WSO2 LLC. (http://www.wso2.com). * - * WSO2 Inc. 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 + * WSO2 LLC. 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 + * 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. + * 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.identity.core.dao; @@ -71,7 +71,7 @@ @PrepareForTest({Transaction.class, IdentityTenantUtil.class}) public class SAMLSSOServiceProviderDAOTest extends PowerMockTestCase { - private SAMLSSOServiceProviderDAO objUnderTest; + private SAMLSSOServiceProviderRegistryDAOImpl objUnderTest; private boolean transactionStarted = false; private Registry mockRegistry; @@ -102,7 +102,7 @@ public Object answer(InvocationOnMock invocationOnMock) throws Throwable { } }).when(mockRegistry).beginTransaction(); - objUnderTest = new SAMLSSOServiceProviderDAO(mockRegistry); + objUnderTest = new SAMLSSOServiceProviderRegistryDAOImpl(mockRegistry); when(mockRegistry.newResource()).thenReturn(new ResourceImpl()); } From 44b8576a06dd42a62422c1aadf02c03e9921c020 Mon Sep 17 00:00:00 2001 From: Osara-B Date: Fri, 20 Dec 2024 10:23:15 +0530 Subject: [PATCH 2/2] Improve SAML persistence layer --- .../core/SAMLSSOServiceProviderManager.java | 90 ++------------ .../core/dao/SAMLSSOServiceProviderDAO.java | 36 ++++-- ...SAMLSSOServiceProviderRegistryDAOImpl.java | 116 +++++++++--------- .../IdentityPersistenceManager.java | 34 +++-- .../dao/SAMLSSOServiceProviderDAOTest.java | 78 ++++++------ 5 files changed, 157 insertions(+), 197 deletions(-) diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java index 97b068372bdc..297c8205258f 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManager.java @@ -18,15 +18,10 @@ package org.wso2.carbon.identity.core; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderDAO; import org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderRegistryDAOImpl; import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO; -import org.wso2.carbon.identity.core.util.IdentityTenantUtil; -import org.wso2.carbon.registry.api.RegistryException; -import org.wso2.carbon.registry.core.Registry; /** * This class is used for managing SAML SSO providers. Adding, retrieving and removing service @@ -34,20 +29,7 @@ */ public class SAMLSSOServiceProviderManager { - private static final Log LOG = LogFactory.getLog(SAMLSSOServiceProviderManager.class); - - /** - * Build the SAML service provider. - * - * @param tenantId Tenant ID. - * @return SAML service provider. - */ - private SAMLSSOServiceProviderDAO buildSAMLSSOProvider(int tenantId) throws RegistryException { - - Registry registry = IdentityTenantUtil.getRegistryService().getConfigSystemRegistry(tenantId); - return new SAMLSSOServiceProviderRegistryDAOImpl(registry); - } - + private static SAMLSSOServiceProviderDAO serviceProviderDAO = new SAMLSSOServiceProviderRegistryDAOImpl(); /** * Add a saml service provider. @@ -60,13 +42,7 @@ private SAMLSSOServiceProviderDAO buildSAMLSSOProvider(int tenantId) throws Regi public boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws IdentityException { - try { - SAMLSSOServiceProviderDAO serviceProviderDAO = buildSAMLSSOProvider(tenantId); - return serviceProviderDAO.addServiceProvider(serviceProviderDO); - } catch (RegistryException e) { - LOG.error("Error while adding service provider", e); - throw new IdentityException("Error while retrieving registry", e); - } + return serviceProviderDAO.addServiceProvider(serviceProviderDO, tenantId); } /** @@ -81,13 +57,7 @@ public boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, in public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, String currentIssuer, int tenantId) throws IdentityException { - try { - SAMLSSOServiceProviderDAO serviceProviderDAO = buildSAMLSSOProvider(tenantId); - return serviceProviderDAO.updateServiceProvider(serviceProviderDO, currentIssuer); - } catch (RegistryException e) { - LOG.error("Error while updating service provider", e); - throw new IdentityException("Error while retrieving registry", e); - } + return serviceProviderDAO.updateServiceProvider(serviceProviderDO, currentIssuer, tenantId); } /** @@ -97,16 +67,9 @@ public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, * @return Array of SAMLSSOServiceProviderDO. * @throws IdentityException Error when getting the SAML service providers. */ - public SAMLSSOServiceProviderDO[] getServiceProviders(int tenantId) - throws IdentityException { + public SAMLSSOServiceProviderDO[] getServiceProviders(int tenantId) throws IdentityException { - try { - SAMLSSOServiceProviderDAO serviceProviderDOA = buildSAMLSSOProvider(tenantId); - return serviceProviderDOA.getServiceProviders(); - } catch (RegistryException e) { - LOG.error("Error while getting service providers", e); - throw new IdentityException("Error while retrieving registry", e); - } + return serviceProviderDAO.getServiceProviders(tenantId); } /** @@ -117,17 +80,9 @@ public SAMLSSOServiceProviderDO[] getServiceProviders(int tenantId) * @return SAMLSSOServiceProviderDO * @throws IdentityException Error when getting the SAML service provider. */ - public SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId) - throws IdentityException { - - try { - SAMLSSOServiceProviderDAO serviceProviderDAO = buildSAMLSSOProvider(tenantId); - return serviceProviderDAO.getServiceProvider(issuer); - } catch (RegistryException e) { - LOG.error("Error while getting service provider", e); - throw new IdentityException("Error while retrieving SAML issuer " + e.getMessage()); - } + public SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId) throws IdentityException { + return serviceProviderDAO.getServiceProvider(issuer, tenantId); } /** @@ -141,13 +96,7 @@ public SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId) public boolean isServiceProviderExists(String issuer, int tenantId) throws IdentityException { - try { - SAMLSSOServiceProviderDAO serviceProviderDAO = buildSAMLSSOProvider(tenantId); - return serviceProviderDAO.isServiceProviderExists(issuer); - } catch (RegistryException e) { - LOG.error("Error while getting service provider", e); - throw new IdentityException("Error while retrieving SAML issuer " + e.getMessage()); - } + return serviceProviderDAO.isServiceProviderExists(issuer, tenantId); } /** @@ -157,16 +106,9 @@ public boolean isServiceProviderExists(String issuer, int tenantId) * @param tenantId Tenant ID. * @throws IdentityException Error when removing the SAML configuration. */ - public boolean removeServiceProvider(String issuer, int tenantId) - throws IdentityException { + public boolean removeServiceProvider(String issuer, int tenantId) throws IdentityException { - try { - SAMLSSOServiceProviderDAO serviceProviderDAO = buildSAMLSSOProvider(tenantId); - return serviceProviderDAO.removeServiceProvider(issuer); - } catch (RegistryException e) { - LOG.error("Error while removing service provider", e); - throw new IdentityException("Error while deleting SAML issuer " + e.getMessage()); - } + return serviceProviderDAO.removeServiceProvider(issuer, tenantId); } /** @@ -177,15 +119,9 @@ public boolean removeServiceProvider(String issuer, int tenantId) * @return SAML service provider information object. * @throws IdentityException Error when uploading the SAML configuration. */ - public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO samlssoServiceProviderDO, int tenantId) - throws IdentityException { + public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO samlssoServiceProviderDO, + int tenantId) throws IdentityException { - try { - SAMLSSOServiceProviderDAO serviceProviderDAO = buildSAMLSSOProvider(tenantId); - return serviceProviderDAO.uploadServiceProvider(samlssoServiceProviderDO); - } catch (RegistryException e) { - LOG.error("Error while uploading service provider", e); - throw new IdentityException("Error while uploading SAML issuer " + e.getMessage()); - } + return serviceProviderDAO.uploadServiceProvider(samlssoServiceProviderDO, tenantId); } } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAO.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAO.java index ad59bf39d5de..b46d705f582d 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAO.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderDAO.java @@ -21,70 +21,80 @@ import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO; +/** + * This interface is used to manage the SAML SSO service providers. + */ public interface SAMLSSOServiceProviderDAO { /** * Add the service provider information to the registry. * * @param serviceProviderDO Service provider information object. + * @param tenantId Tenant Id. * @return True if addition successful. * @throws IdentityException Error while persisting to the registry. */ - boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws IdentityException; + boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws IdentityException; /** * Update the service provider if it exists. * - * @param serviceProviderDO Service provider to be updated. - * @param currentIssuer Issuer of the service provider before the update. + * @param serviceProviderDO Service provider to be updated. + * @param currentIssuer Issuer of the service provider before the update. + * @param tenantId Tenant Id. * @return True if the update is successful. * @throws IdentityException If an error occurs while updating the service provider. */ - public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, String currentIssuer) + boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, String currentIssuer, int tenantId) throws IdentityException; /** * Get all the service providers. * + * @param tenantId Tenant Id. * @return Array of service providers. * @throws IdentityException Error occurred while retrieving the service providers from registry. */ - SAMLSSOServiceProviderDO[] getServiceProviders() throws IdentityException; + SAMLSSOServiceProviderDO[] getServiceProviders(int tenantId) throws IdentityException; /** * Remove the service provider with the given name. * + * @param issuer Name of the SAML issuer. + * @param tenantId Tenant Id. * @return True if deletion success. - * @param issuer Name of the SAML issuer. * @throws IdentityException Error occurred while removing the SAML service provider from registry. */ - boolean removeServiceProvider(String issuer) throws IdentityException; + boolean removeServiceProvider(String issuer, int tenantId) throws IdentityException; /** * Get the service provider. * - * @param issuer Name of the SAML issuer. + * @param issuer Name of the SAML issuer. + * @param tenantId tenant Id. * @return Service provider information object. * @throws IdentityException Error occurred while retrieving the SAML service provider from registry. */ - SAMLSSOServiceProviderDO getServiceProvider(String issuer) throws IdentityException; + SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId) throws IdentityException; /** * Check whether the service provider exists. * - * @param issuer Name of the SAML issuer. + * @param issuer Name of the SAML issuer. + * @param tenantId Tenant Id. * @return True if service provider exists. * @throws IdentityException Error occurred while checking the existence of the SAML service provider. */ - boolean isServiceProviderExists(String issuer) throws IdentityException; + boolean isServiceProviderExists(String issuer, int tenantId) throws IdentityException; /** * Upload service Provider using metadata file. * * @param serviceProviderDO Service provider information object. + * @param tenantId Tenant Id. * @return True if upload success. * @throws IdentityException Error occurred while adding the information to registry. */ - SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws - IdentityException; + SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) + throws IdentityException; } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderRegistryDAOImpl.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderRegistryDAOImpl.java index 08ac0b769c89..84e410a5d70e 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderRegistryDAOImpl.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/SAMLSSOServiceProviderRegistryDAOImpl.java @@ -52,8 +52,12 @@ import static org.wso2.carbon.identity.core.util.JdbcUtils.isH2DB; +/** + * This class is used for managing SAML SSO service providers in the Registry. + */ public class SAMLSSOServiceProviderRegistryDAOImpl extends AbstractDAO implements SAMLSSOServiceProviderDAO { + private static final String CERTIFICATE_PROPERTY_NAME = "CERTIFICATE"; private static final String QUERY_TO_GET_APPLICATION_CERTIFICATE_ID = "SELECT " + "META.VALUE FROM SP_INBOUND_AUTH INBOUND, SP_APP SP, SP_METADATA META WHERE SP.ID = INBOUND.APP_ID AND " + @@ -63,10 +67,9 @@ public class SAMLSSOServiceProviderRegistryDAOImpl extends AbstractDAO serviceProvidersList = new ArrayList<>(); try { if (registry.resourceExists(IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS)) { @@ -569,7 +567,7 @@ public SAMLSSOServiceProviderDO[] getServiceProviders() throws IdentityException Collection samlSSOServiceProvidersCollection = (Collection) samlSSOServiceProvidersResource; String[] resources = samlSSOServiceProvidersCollection.getChildren(); for (String resource : resources) { - getChildResources(resource, serviceProvidersList); + getChildResources(resource, serviceProvidersList, registry); } } } @@ -580,14 +578,10 @@ public SAMLSSOServiceProviderDO[] getServiceProviders() throws IdentityException return serviceProvidersList.toArray(new SAMLSSOServiceProviderDO[serviceProvidersList.size()]); } - /** - * Remove the service provider with the given name. - * @return True if deletion success. - * @param issuer Name of the SAML issuer. - * @throws IdentityException Error occurred while removing the SAML service provider from registry. - */ - public boolean removeServiceProvider(String issuer) throws IdentityException { + @Override + public boolean removeServiceProvider(String issuer, int tenantId) throws IdentityException { + Registry registry = getRegistry(tenantId); if (issuer == null || StringUtils.isEmpty(issuer.trim())) { throw new IllegalArgumentException("Trying to delete issuer \'" + issuer + "\'"); } @@ -616,19 +610,14 @@ public boolean removeServiceProvider(String issuer) throws IdentityException { log.error(msg, e); throw IdentityException.error(msg, e); } finally { - commitOrRollbackTransaction(isErrorOccurred); + commitOrRollbackTransaction(isErrorOccurred, registry); } } - /** - * Get the service provider. - * - * @param issuer - * @return - * @throws IdentityException - */ - public SAMLSSOServiceProviderDO getServiceProvider(String issuer) throws IdentityException { + @Override + public SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId) throws IdentityException { + Registry registry = getRegistry(tenantId); String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(issuer); SAMLSSOServiceProviderDO serviceProviderDO = null; @@ -731,7 +720,10 @@ private int getApplicationCertificateId(String issuer, int tenantId) throws SQLE } } - public boolean isServiceProviderExists(String issuer) throws IdentityException { + @Override + public boolean isServiceProviderExists(String issuer, int tenantId) throws IdentityException { + + Registry registry = getRegistry(tenantId); String path = IdentityRegistryResources.SAML_SSO_SERVICE_PROVIDERS + encodePath(issuer); try { return registry.resourceExists(path); @@ -746,15 +738,11 @@ private String encodePath(String path) { return encodedStr.replace("=", ""); } - /** - * Upload service Provider using metadata file.. - * @param serviceProviderDO Service provider information object. - * @return True if upload success. - * @throws IdentityException Error occurred while adding the information to registry. - */ - public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO) throws - IdentityException { + @Override + public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) + throws IdentityException { + Registry registry = getRegistry(tenantId); if (serviceProviderDO == null || serviceProviderDO.getIssuer() == null) { throw new IdentityException("Issuer cannot be found in the provided arguments."); } @@ -792,7 +780,7 @@ public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO s registry.beginTransaction(); } - Resource resource = createResource(serviceProviderDO); + Resource resource = createResource(serviceProviderDO, registry); registry.put(path, resource); if (log.isDebugEnabled()) { if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { @@ -808,7 +796,7 @@ public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO s isErrorOccurred = true; throw IdentityException.error("Error while adding Service Provider.", e); } finally { - commitOrRollbackTransaction(isErrorOccurred); + commitOrRollbackTransaction(isErrorOccurred, registry); } } @@ -817,7 +805,7 @@ public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO s * @param isErrorOccurred Identifier for error transactions. * @throws IdentityException Error while committing or running rollback on the transaction. */ - private void commitOrRollbackTransaction(boolean isErrorOccurred) throws IdentityException { + private void commitOrRollbackTransaction(boolean isErrorOccurred, Registry registry) throws IdentityException { try { // Rollback the transaction if there is an error, Otherwise try to commit. @@ -838,8 +826,8 @@ private void commitOrRollbackTransaction(boolean isErrorOccurred) throws Identit * @param serviceProviderList child resource list. * @throws RegistryException */ - private void getChildResources(String parentResource, List - serviceProviderList) throws RegistryException { + private void getChildResources(String parentResource, List serviceProviderList, + Registry registry) throws RegistryException { if (registry.resourceExists(parentResource)) { Resource resource = registry.get(parentResource); @@ -847,11 +835,21 @@ private void getChildResources(String parentResource, List> dummyAdvProperties; private Map> dummyPropertiesWithAnIssuerQualifier; private MockedStatic transaction; - + private MockedStatic identityTenantUtil; + private static final int TENANT_ID = 1; @BeforeMethod public void setUp() throws Exception { transaction = mockStatic(Transaction.class); mockRegistry = mock(UserRegistry.class); + RegistryService mockRegistryService = mock(RegistryService.class); transaction.when(Transaction::isStarted).thenReturn(transactionStarted); //Mock commit transaction doAnswer(new Answer() { @@ -103,7 +106,10 @@ public Object answer(InvocationOnMock invocationOnMock) throws Throwable { } }).when(mockRegistry).beginTransaction(); - objUnderTest = new SAMLSSOServiceProviderRegistryDAOImpl(mockRegistry); + objUnderTest = new SAMLSSOServiceProviderRegistryDAOImpl(); + identityTenantUtil = mockStatic(IdentityTenantUtil.class); + when(IdentityTenantUtil.getRegistryService()).thenReturn(mockRegistryService); + when(mockRegistryService.getConfigSystemRegistry(TENANT_ID)).thenReturn((UserRegistry) mockRegistry); when(mockRegistry.newResource()).thenReturn(new ResourceImpl()); } @@ -187,6 +193,7 @@ private void setUpResources() throws Exception { @AfterMethod public void tearDown() throws Exception { + identityTenantUtil.close(); transaction.close(); } @@ -348,7 +355,7 @@ public void testAddServiceProvider(Object paramMapObj) throws Exception { + IdentityRegistryResources.QUALIFIER_ID + dummyResource.getProperty(IdentityRegistryResources. PROP_SAML_SSO_ISSUER_QUALIFIER)); } - objUnderTest.addServiceProvider(serviceProviderDO); + objUnderTest.addServiceProvider(serviceProviderDO, TENANT_ID); verify(mockRegistry).put(captor.capture(), any(Resource.class)); assertEquals(captor.getValue(), expectedPath, "Resource is not added at correct path"); } @@ -359,7 +366,7 @@ public void testAddExistingServiceProvider() throws Exception { String existingPath = getPath("existingIssuer"); serviceProviderDO.setIssuer("existingIssuer"); when(mockRegistry.resourceExists(existingPath)).thenReturn(true); - assertFalse(objUnderTest.addServiceProvider(serviceProviderDO), "Resource should not have added."); + assertFalse(objUnderTest.addServiceProvider(serviceProviderDO, TENANT_ID), "Resource should not have added."); } @Test(expectedExceptions = {IdentityException.class}) @@ -369,7 +376,7 @@ public void testAddServiceProviderRegistryError() throws Exception { String existingPath = getPath("erringIssuer"); serviceProviderDO.setIssuer("erringIssuer"); doThrow(RegistryException.class).when(mockRegistry).put(eq(existingPath), any(Resource.class)); - objUnderTest.addServiceProvider(serviceProviderDO); + objUnderTest.addServiceProvider(serviceProviderDO, TENANT_ID); } @Test(dataProvider = "ResourceToObjectData") @@ -388,7 +395,7 @@ public void testUpdateServiceProvider(Object paramMapObj) throws Exception { } String expectedPath = getPath(existingIssuer); when(mockRegistry.resourceExists(expectedPath)).thenReturn(true); - objUnderTest.updateServiceProvider(serviceProviderDO, existingIssuer); + objUnderTest.updateServiceProvider(serviceProviderDO, existingIssuer, TENANT_ID); verify(mockRegistry).put(captor.capture(), any(Resource.class)); assertEquals(captor.getValue(), expectedPath, "Resource is not added at correct path"); } @@ -398,7 +405,7 @@ public void testUpdatingServiceProviderExistingIssuer() throws Exception { SAMLSSOServiceProviderDO serviceProviderDO = new SAMLSSOServiceProviderDO(); serviceProviderDO.setIssuer("newIssuer"); when(mockRegistry.resourceExists(getPath("newIssuer"))).thenReturn(true); - assertFalse(objUnderTest.updateServiceProvider(serviceProviderDO, "existingIssuer"), "Resource should not have updated."); + assertFalse(objUnderTest.updateServiceProvider(serviceProviderDO, "existingIssuer", TENANT_ID), "Resource should not have updated."); } @Test @@ -431,7 +438,7 @@ public void testGetServiceProviders() throws Exception { when(mockRegistry.resourceExists(paths[0])).thenReturn(true); when(mockRegistry.resourceExists(paths[1])).thenReturn(true); when(mockRegistry.resourceExists(paths[2])).thenReturn(true); - SAMLSSOServiceProviderDO[] serviceProviders = objUnderTest.getServiceProviders(); + SAMLSSOServiceProviderDO[] serviceProviders = objUnderTest.getServiceProviders(TENANT_ID); assertEquals(serviceProviders.length, 3, "Should have returned 3 service providers."); } @@ -440,7 +447,7 @@ public void testRemoveServiceProvider() throws Exception { String existingIssuer = "ExistingIssuer"; String path = getPath(existingIssuer); when(mockRegistry.resourceExists(path)).thenReturn(true); - assertTrue(objUnderTest.removeServiceProvider(existingIssuer), "SP Resource is not deleted from path"); + assertTrue(objUnderTest.removeServiceProvider(existingIssuer, TENANT_ID), "SP Resource is not deleted from path"); } @Test @@ -448,40 +455,39 @@ public void testRemoveNonExistingServiceProvider() throws Exception { String nonExistingIssuer = "NonExistingIssuer"; String path = getPath(nonExistingIssuer); when(mockRegistry.resourceExists(path)).thenReturn(false); - assertFalse(objUnderTest.removeServiceProvider(nonExistingIssuer), "SP Resource should not have existed to " + + assertFalse(objUnderTest.removeServiceProvider(nonExistingIssuer, TENANT_ID), "SP Resource should not have existed to " + "delete."); } @Test(expectedExceptions = IllegalArgumentException.class) public void testRemoveEmptyServiceProvider() throws Exception { - objUnderTest.removeServiceProvider(""); + objUnderTest.removeServiceProvider("", TENANT_ID); fail("SP Resource with empty name could not have been deleted."); } @Test public void testGetServiceProvider() throws Exception { - try (MockedStatic identityTenantUtil = mockStatic(IdentityTenantUtil.class)) { - RealmService mockRealmService = mock(RealmService.class); - TenantManager mockTenantManager = mock(TenantManager.class); - identityTenantUtil.when(IdentityTenantUtil::getRealmService).thenReturn(mockRealmService); - when(mockRealmService.getTenantManager()).thenReturn(mockTenantManager); - when(mockTenantManager.getDomain(anyInt())).thenReturn("test.com"); - - Properties dummyResourceProperties = new Properties(); - dummyResourceProperties.putAll(dummyBasicProperties); - Resource dummyResource = new ResourceImpl(); - dummyResource.setProperties(dummyResourceProperties); - - String path = getPath(dummyResource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER)); - when(mockRegistry.resourceExists(path)).thenReturn(true); - when(mockRegistry.get(path)).thenReturn(dummyResource); - - SAMLSSOServiceProviderDO serviceProviderDO = objUnderTest.getServiceProvider(dummyResource.getProperty - (IdentityRegistryResources.PROP_SAML_SSO_ISSUER)); - assertEquals(serviceProviderDO.getTenantDomain(), "test.com", - "Retrieved resource's tenant domain mismatch"); - } + RealmService mockRealmService = mock(RealmService.class); + TenantManager mockTenantManager = mock(TenantManager.class); + identityTenantUtil.when(IdentityTenantUtil::getRealmService).thenReturn(mockRealmService); + when(mockRealmService.getTenantManager()).thenReturn(mockTenantManager); + when(mockTenantManager.getDomain(anyInt())).thenReturn("test.com"); + + Properties dummyResourceProperties = new Properties(); + dummyResourceProperties.putAll(dummyBasicProperties); + Resource dummyResource = new ResourceImpl(); + dummyResource.setProperties(dummyResourceProperties); + + String path = getPath(dummyResource.getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER)); + when(mockRegistry.resourceExists(path)).thenReturn(true); + when(mockRegistry.get(path)).thenReturn(dummyResource); + + SAMLSSOServiceProviderDO serviceProviderDO = objUnderTest.getServiceProvider(dummyResource.getProperty + (IdentityRegistryResources.PROP_SAML_SSO_ISSUER), TENANT_ID); + assertEquals(serviceProviderDO.getTenantDomain(), "test.com", + "Retrieved resource's tenant domain mismatch"); + } @Test @@ -489,7 +495,7 @@ public void testIsServiceProviderExists() throws Exception { String validSP = "ValidSP"; String path = getPath(validSP); when(mockRegistry.resourceExists(path)).thenReturn(true); - assertTrue(objUnderTest.isServiceProviderExists(validSP)); + assertTrue(objUnderTest.isServiceProviderExists(validSP, TENANT_ID)); } @Test @@ -497,7 +503,7 @@ public void testNonExistingSPIsServiceProviderExists() throws Exception { String invalidSP = "InvalidSP"; String path = getPath(invalidSP); when(mockRegistry.resourceExists(path)).thenReturn(false); - assertFalse(objUnderTest.isServiceProviderExists(invalidSP)); + assertFalse(objUnderTest.isServiceProviderExists(invalidSP, TENANT_ID)); } @Test @@ -511,7 +517,7 @@ public void testUploadServiceProvider() throws Exception { .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER)); when(mockRegistry.resourceExists(expectedPath)).thenReturn(false); SAMLSSOServiceProviderDO serviceProviderDO = objUnderTest.resourceToObject(dummyResource); - assertEquals(objUnderTest.uploadServiceProvider(serviceProviderDO), serviceProviderDO, "Same resource should" + + assertEquals(objUnderTest.uploadServiceProvider(serviceProviderDO, TENANT_ID), serviceProviderDO, "Same resource should" + " have returned after successful upload."); } @@ -526,7 +532,7 @@ public void testUploadExistingServiceProvider() throws Exception { .getProperty(IdentityRegistryResources.PROP_SAML_SSO_ISSUER)); when(mockRegistry.resourceExists(expectedPath)).thenReturn(true); SAMLSSOServiceProviderDO serviceProviderDO = objUnderTest.resourceToObject(dummyResource); - objUnderTest.uploadServiceProvider(serviceProviderDO); + objUnderTest.uploadServiceProvider(serviceProviderDO, TENANT_ID); fail("Uploading an existing SP should have failed"); }