diff --git a/components/identity-core/org.wso2.carbon.identity.core/pom.xml b/components/identity-core/org.wso2.carbon.identity.core/pom.xml index baf9f2862eb5..68e4d608a022 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/pom.xml +++ b/components/identity-core/org.wso2.carbon.identity.core/pom.xml @@ -142,6 +142,11 @@ xml-apis xml-apis + + com.h2database + h2 + test + 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 b2b0040a84a4..7e8907e688c7 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 @@ -29,15 +29,16 @@ */ public class SAMLSSOServiceProviderManager { - SAMLServiceProviderPersistenceManagerFactory - samlSSOPersistenceManagerFactory = new SAMLServiceProviderPersistenceManagerFactory(); - SAMLSSOServiceProviderDAO serviceProviderDAO = samlSSOPersistenceManagerFactory.getSAMLServiceProviderPersistenceManager(); + SAMLServiceProviderPersistenceManagerFactory samlSSOPersistenceManagerFactory = + new SAMLServiceProviderPersistenceManagerFactory(); + SAMLSSOServiceProviderDAO serviceProviderDAO = + samlSSOPersistenceManagerFactory.getSAMLServiceProviderPersistenceManager(); /** * Add a saml service provider. * - * @param serviceProviderDO Service provider information object. - * @param tenantId Tenant ID. + * @param serviceProviderDO Service provider information object. + * @param tenantId Tenant ID. * @return True if success. * @throws IdentityException Error when adding the SAML service provider. */ @@ -50,9 +51,9 @@ public boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, in /** * Update a saml service provider if already exists. * - * @param serviceProviderDO Service provider information object. - * @param currentIssuer Issuer of the service provider before the update. - * @param tenantId Tenant ID. + * @param serviceProviderDO Service provider information object. + * @param currentIssuer Issuer of the service provider before the update. + * @param tenantId Tenant ID. * @return True if success. * @throws IdentityException Error when updating the SAML service provider. */ @@ -65,7 +66,7 @@ public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, /** * Get all the saml service providers. * - * @param tenantId Tenant ID. + * @param tenantId Tenant ID. * @return Array of SAMLSSOServiceProviderDO. * @throws IdentityException Error when getting the SAML service providers. */ @@ -77,8 +78,8 @@ public SAMLSSOServiceProviderDO[] getServiceProviders(int tenantId) throws Ident /** * Get SAML issuer properties from service provider by saml issuer name. * - * @param issuer SAML issuer name. - * @param tenantId Tenant ID. + * @param issuer SAML issuer name. + * @param tenantId Tenant ID. * @return SAMLSSOServiceProviderDO * @throws IdentityException Error when getting the SAML service provider. */ @@ -90,13 +91,12 @@ public SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId) /** * Check whether SAML issuer exists by saml issuer name. * - * @param issuer SAML issuer name. - * @param tenantId Tenant ID. + * @param issuer SAML issuer name. + * @param tenantId Tenant ID. * @return True if exists * @throws IdentityException Error when checking the SAML service provider. */ - public boolean isServiceProviderExists(String issuer, int tenantId) - throws IdentityException { + public boolean isServiceProviderExists(String issuer, int tenantId) throws IdentityException { return serviceProviderDAO.isServiceProviderExists(issuer, tenantId); } @@ -104,8 +104,8 @@ public boolean isServiceProviderExists(String issuer, int tenantId) /** * Removes the SAML configuration related to the application, idenfied by the issuer. * - * @param issuer Issuer of the SAML application. - * @param tenantId Tenant ID. + * @param issuer Issuer of the SAML application. + * @param tenantId Tenant ID. * @throws IdentityException Error when removing the SAML configuration. */ public boolean removeServiceProvider(String issuer, int tenantId) throws IdentityException { @@ -116,8 +116,8 @@ public boolean removeServiceProvider(String issuer, int tenantId) throws Identit /** * Upload the SAML configuration related to the application, using metadata. * - * @param samlssoServiceProviderDO SAML service provider information object. - * @param tenantId Tenant ID. + * @param samlssoServiceProviderDO SAML service provider information object. + * @param tenantId Tenant ID. * @return SAML service provider information object. * @throws IdentityException Error when uploading the SAML configuration. */ diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/JDBCSAMLSSOServiceProviderDAOImpl.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/JDBCSAMLSSOServiceProviderDAOImpl.java new file mode 100644 index 000000000000..b2c8aaf6c234 --- /dev/null +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/JDBCSAMLSSOServiceProviderDAOImpl.java @@ -0,0 +1,626 @@ +/* + * Copyright (c) 2024, 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.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate; +import org.wso2.carbon.database.utils.jdbc.NamedPreparedStatement; +import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; +import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException; +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.ServiceProviderProperty; +import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.core.util.JdbcUtils; +import org.wso2.carbon.user.api.Tenant; + +import java.security.cert.X509Certificate; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +import static org.wso2.carbon.identity.core.util.JdbcUtils.isH2DB; + +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML_SCHEMA_VERSION; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.CERTIFICATE_PROPERTY_NAME; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ID; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.TENANT_ID; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ISSUER; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.DEFAULT_ASSERTION_CONSUMER_URL; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.NAME_ID_FORMAT; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.CERT_ALIAS; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.REQ_SIG_VALIDATION; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SIGN_RESPONSE; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SIGN_ASSERTIONS; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SIGNING_ALGO; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.DIGEST_ALGO; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ENCRYPT_ASSERTION; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ASSERTION_ENCRYPTION_ALGO; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.KEY_ENCRYPTION_ALGO; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ATTR_PROFILE_ENABLED; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ATTR_SERVICE_INDEX; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SLO_PROFILE_ENABLED; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SLO_METHOD; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SLO_RESPONSE_URL; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SLO_REQUEST_URL; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.IDP_INIT_SSO_ENABLED; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.IDP_INIT_SLO_ENABLED; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.QUERY_REQUEST_PROFILE_ENABLED; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ECP_ENABLED; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ARTIFACT_BINDING_ENABLED; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ARTIFACT_RESOLVE_REQ_SIG_VALIDATION; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.IDP_ENTITY_ID_ALIAS; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.ISSUER_QUALIFIER; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.VERSION; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.CREATED_AT; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.UPDATED_AT; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.PROPERTY_NAME; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.PROPERTY_VALUE; +import static org.wso2.carbon.identity.core.dao.SAMLSSOServiceProviderConstants.SAML2TableColumns.SP_ID; + +import static java.time.ZoneOffset.UTC; + +/** + * Implementation of the SAMLSSOServiceProviderDAO interface for JDBC-based persistence. + */ +public class JDBCSAMLSSOServiceProviderDAOImpl implements SAMLSSOServiceProviderDAO { + + private final Calendar CALENDAR = Calendar.getInstance(TimeZone.getTimeZone(UTC)); + private static final Log LOG = LogFactory.getLog(JDBCSAMLSSOServiceProviderDAOImpl.class); + + public JDBCSAMLSSOServiceProviderDAOImpl() { + + } + + @Override + public boolean addServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws IdentityException { + + validateServiceProvider(serviceProviderDO); + try { + if (processIsServiceProviderExists(serviceProviderDO.getIssuer(),tenantId)) { + debugLog(serviceProviderInfo(serviceProviderDO) + " already exists."); + return false; + } + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + namedJdbcTemplate.withTransaction(template -> { + processAddServiceProvider(serviceProviderDO, tenantId); + processAddSPProperties(serviceProviderDO, tenantId); + return null; + }); + debugLog(serviceProviderInfo(serviceProviderDO) + " is added successfully."); + return true; + } catch (TransactionException | DataAccessException e) { + String msg = "Error while adding " + serviceProviderInfo(serviceProviderDO); + throw new IdentityException(msg, e); + } + } + + @Override + public boolean updateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, String currentIssuer, int tenantId) + throws IdentityException { + + validateServiceProvider(serviceProviderDO); + String newIssuer = serviceProviderDO.getIssuer(); + boolean isIssuerUpdated = !StringUtils.equals(currentIssuer, newIssuer); + + try { + if (isIssuerUpdated && processIsServiceProviderExists(newIssuer, tenantId)) { + debugLog(serviceProviderInfo(serviceProviderDO) + " already exists."); + return false; + } + int serviceProviderId = processGetServiceProviderId(currentIssuer, tenantId); + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + namedJdbcTemplate.withTransaction(template -> { + processUpdateServiceProvider(serviceProviderDO, serviceProviderId, tenantId); + processUpdateSPProperties(serviceProviderDO, serviceProviderId); + return null; + }); + debugLog(serviceProviderInfo(serviceProviderDO) + " is updated successfully."); + return true; + } catch (TransactionException | DataAccessException e) { + String msg = "Error while updating " + serviceProviderInfo(serviceProviderDO); + throw new IdentityException(msg, e); + } + } + + @Override + public SAMLSSOServiceProviderDO[] getServiceProviders(int tenantId) throws IdentityException { + + List serviceProvidersList; + try { + serviceProvidersList = processGetServiceProviders(tenantId); + } catch (DataAccessException e) { + throw new IdentityException("Error reading Service Providers", e); + } + return serviceProvidersList.toArray(new SAMLSSOServiceProviderDO[0]); + } + + @Override + public boolean removeServiceProvider(String issuer, int tenantId) throws IdentityException { + + if (StringUtils.isBlank(issuer)) { + throw new IllegalArgumentException("Trying to delete issuer \'" + issuer + "\'"); + } + try { + if (!processIsServiceProviderExists(issuer, tenantId)) { + debugLog("Service Provider with issuer " + issuer + " does not exist."); + return false; + } + processDeleteServiceProvider(issuer, tenantId); + return true; + } catch (DataAccessException e) { + String msg = "Error removing the service provider with name: " + issuer; + throw new IdentityException(msg, e); + } + } + + @Override + public SAMLSSOServiceProviderDO getServiceProvider(String issuer, int tenantId) throws IdentityException { + + SAMLSSOServiceProviderDO serviceProviderDO = null; + + try { + if (isServiceProviderExists(issuer, tenantId)) { + serviceProviderDO = processGetServiceProvider(issuer, tenantId); + } + } catch (DataAccessException e) { + throw IdentityException.error(String.format( + "An error occurred while retrieving the " + "the service provider with the issuer '%s'", issuer), + e); + } + if (serviceProviderDO == null) { + return null; + } + try { + String tenantDomain = IdentityTenantUtil.getTenantDomain(tenantId); + // Load the certificate stored in the database, if signature validation is enabled. + if (serviceProviderDO.isDoValidateSignatureInRequests() || + serviceProviderDO.isDoValidateSignatureInArtifactResolve() || + serviceProviderDO.isDoEnableEncryptedAssertion()) { + + Tenant tenant = IdentityTenantUtil.getTenant(tenantId); + serviceProviderDO.setX509Certificate(getApplicationCertificate(serviceProviderDO, tenant)); + } + serviceProviderDO.setTenantDomain(tenantDomain); + } catch (DataAccessException | 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; + } + + @Override + public boolean isServiceProviderExists(String issuer, int tenantId) throws IdentityException { + + try { + return processIsServiceProviderExists(issuer, tenantId); + } catch (DataAccessException e) { + String msg = "Error while checking existence of Service Provider with issuer: " + issuer; + throw new IdentityException(msg, e); + } + } + + @Override + public SAMLSSOServiceProviderDO uploadServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) + throws IdentityException { + + validateServiceProvider(serviceProviderDO); + if (serviceProviderDO.getDefaultAssertionConsumerUrl() == null) { + throw new IdentityException("No default assertion consumer URL provided for service provider :" + + serviceProviderDO.getIssuer()); + } + + try { + if (processIsServiceProviderExists(serviceProviderDO.getIssuer(), tenantId)) { + debugLog(serviceProviderInfo(serviceProviderDO) + " already exists."); + throw new IdentityException(serviceProviderInfo(serviceProviderDO) + " already exists."); + } + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + namedJdbcTemplate.withTransaction(template -> { + processAddServiceProvider(serviceProviderDO, tenantId); + processAddSPProperties(serviceProviderDO, tenantId); + return null; + }); + debugLog(serviceProviderInfo(serviceProviderDO) + " is added successfully."); + return serviceProviderDO; + } catch (TransactionException | DataAccessException e) { + String msg = "Error while adding " + serviceProviderInfo(serviceProviderDO); + throw new IdentityException(msg, e); + } + } + + private void debugLog(String message) { + + if (LOG.isDebugEnabled()) { + LOG.debug(message); + } + } + + private boolean processIsServiceProviderExists(String issuer, int tenantId) throws DataAccessException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + Integer serviceProviderId = + namedJdbcTemplate.fetchSingleRecord(SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML_SP_ID_BY_ISSUER, + (resultSet, rowNumber) -> resultSet.getInt(ID), preparedStatement -> { + preparedStatement.setString(ISSUER, issuer); + preparedStatement.setInt(TENANT_ID, tenantId); + }); + return serviceProviderId != null; + } + + private void validateServiceProvider(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 (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier()) && + !serviceProviderDO.getIssuer().contains(IdentityRegistryResources.QUALIFIER_ID)) { + serviceProviderDO.setIssuer( + getIssuerWithQualifier(serviceProviderDO.getIssuer(), serviceProviderDO.getIssuerQualifier())); + } + } + + private String serviceProviderInfo(SAMLSSOServiceProviderDO serviceProviderDO) { + + if (StringUtils.isNotBlank(serviceProviderDO.getIssuerQualifier())) { + return "SAML2 Service Provider with issuer: " + getIssuerWithoutQualifier(serviceProviderDO.getIssuer()) + + " and qualifier name " + serviceProviderDO.getIssuerQualifier(); + } else { + return "SAML2 Service Provider with issuer: " + serviceProviderDO.getIssuer(); + } + } + + /** + * 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) { + + return issuer + IdentityRegistryResources.QUALIFIER_ID + qualifier; + } + + /** + * 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) { + + return StringUtils.substringBeforeLast(issuerWithQualifier, IdentityRegistryResources.QUALIFIER_ID); + } + + private SAMLSSOServiceProviderDO resourceToObject(ResultSet resultSet) throws SQLException { + + SAMLSSOServiceProviderDO serviceProviderDO = new SAMLSSOServiceProviderDO(); + + serviceProviderDO.setIssuer(resultSet.getString(ISSUER)); + serviceProviderDO.setDefaultAssertionConsumerUrl(resultSet.getString(DEFAULT_ASSERTION_CONSUMER_URL)); + serviceProviderDO.setNameIDFormat(resultSet.getString(NAME_ID_FORMAT)); + serviceProviderDO.setCertAlias(resultSet.getString(CERT_ALIAS)); + serviceProviderDO.setDoValidateSignatureInRequests(resultSet.getBoolean(REQ_SIG_VALIDATION)); + serviceProviderDO.setDoSignResponse(resultSet.getBoolean(SIGN_RESPONSE)); + serviceProviderDO.setDoSignAssertions(resultSet.getBoolean(SIGN_ASSERTIONS)); + serviceProviderDO.setSigningAlgorithmUri(resultSet.getString(SIGNING_ALGO)); + serviceProviderDO.setDigestAlgorithmUri(resultSet.getString(DIGEST_ALGO)); + serviceProviderDO.setDoEnableEncryptedAssertion(resultSet.getBoolean(ENCRYPT_ASSERTION)); + serviceProviderDO.setAssertionEncryptionAlgorithmUri(resultSet.getString(ASSERTION_ENCRYPTION_ALGO)); + serviceProviderDO.setKeyEncryptionAlgorithmUri(resultSet.getString(KEY_ENCRYPTION_ALGO)); + serviceProviderDO.setEnableAttributesByDefault(resultSet.getBoolean(ATTR_PROFILE_ENABLED)); + serviceProviderDO.setAttributeConsumingServiceIndex(resultSet.getString(ATTR_SERVICE_INDEX)); + serviceProviderDO.setDoSingleLogout(resultSet.getBoolean(SLO_PROFILE_ENABLED)); + serviceProviderDO.setSloResponseURL(resultSet.getString(SLO_RESPONSE_URL)); + serviceProviderDO.setSloRequestURL(resultSet.getString(SLO_REQUEST_URL)); + serviceProviderDO.setIdPInitSSOEnabled(resultSet.getBoolean(IDP_INIT_SSO_ENABLED)); + serviceProviderDO.setIdPInitSLOEnabled(resultSet.getBoolean(IDP_INIT_SLO_ENABLED)); + serviceProviderDO.setAssertionQueryRequestProfileEnabled(resultSet.getBoolean(QUERY_REQUEST_PROFILE_ENABLED)); + serviceProviderDO.setSamlECP(resultSet.getBoolean(ECP_ENABLED)); + serviceProviderDO.setEnableSAML2ArtifactBinding(resultSet.getBoolean(ARTIFACT_BINDING_ENABLED)); + serviceProviderDO.setDoValidateSignatureInArtifactResolve( + resultSet.getBoolean(ARTIFACT_RESOLVE_REQ_SIG_VALIDATION)); + serviceProviderDO.setIdpEntityIDAlias(resultSet.getString(IDP_ENTITY_ID_ALIAS)); + serviceProviderDO.setIssuerQualifier(resultSet.getString(ISSUER_QUALIFIER)); + serviceProviderDO.setSupportedAssertionQueryRequestTypes( + resultSet.getString(SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES)); + serviceProviderDO.setDoFrontChannelLogout(!"BackChannel".equals(resultSet.getString(SLO_METHOD))); + if (serviceProviderDO.isDoFrontChannelLogout()) { + serviceProviderDO.setFrontChannelLogoutBinding(resultSet.getString(SLO_METHOD)); + } + + return serviceProviderDO; + } + + private void addProperties(int serviceProviderId, SAMLSSOServiceProviderDO serviceProviderDO) + throws DataAccessException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + List properties = + namedJdbcTemplate.executeQuery(SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML_SSO_ATTR_BY_ID, + (resultSet, rowNumber) -> new ServiceProviderProperty(resultSet.getString(PROPERTY_NAME), + resultSet.getString(PROPERTY_VALUE)), + namedPreparedStatement -> namedPreparedStatement.setInt(SP_ID, serviceProviderId)); + serviceProviderDO.addMultiValuedProperties(properties); + } + + private void setUpdateServiceProviderParameters(NamedPreparedStatement statement, + SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws SQLException { + + statement.setInt(TENANT_ID, tenantId); + statement.setString(ISSUER, serviceProviderDO.getIssuer()); + statement.setString(DEFAULT_ASSERTION_CONSUMER_URL, serviceProviderDO.getDefaultAssertionConsumerUrl()); + statement.setString(NAME_ID_FORMAT, serviceProviderDO.getNameIDFormat()); + statement.setString(CERT_ALIAS, serviceProviderDO.getCertAlias()); + statement.setBoolean(REQ_SIG_VALIDATION, serviceProviderDO.isDoValidateSignatureInRequests()); + statement.setBoolean(SIGN_RESPONSE, serviceProviderDO.isDoSignResponse()); + statement.setBoolean(SIGN_ASSERTIONS, serviceProviderDO.isDoSignAssertions()); + statement.setString(SIGNING_ALGO, serviceProviderDO.getSigningAlgorithmUri()); + statement.setString(DIGEST_ALGO, serviceProviderDO.getDigestAlgorithmUri()); + statement.setBoolean(ENCRYPT_ASSERTION, serviceProviderDO.isDoEnableEncryptedAssertion()); + statement.setString(ASSERTION_ENCRYPTION_ALGO, serviceProviderDO.getAssertionEncryptionAlgorithmUri()); + statement.setString(KEY_ENCRYPTION_ALGO, serviceProviderDO.getKeyEncryptionAlgorithmUri()); + statement.setBoolean(ATTR_PROFILE_ENABLED, serviceProviderDO.isEnableAttributesByDefault()); + statement.setString(ATTR_SERVICE_INDEX, serviceProviderDO.getAttributeConsumingServiceIndex()); + statement.setBoolean(SLO_PROFILE_ENABLED, serviceProviderDO.isDoSingleLogout()); + statement.setString(SLO_METHOD, serviceProviderDO.getSingleLogoutMethod()); + statement.setString(SLO_RESPONSE_URL, serviceProviderDO.getSloResponseURL()); + statement.setString(SLO_REQUEST_URL, serviceProviderDO.getSloRequestURL()); + statement.setBoolean(IDP_INIT_SSO_ENABLED, serviceProviderDO.isIdPInitSSOEnabled()); + statement.setBoolean(IDP_INIT_SLO_ENABLED, serviceProviderDO.isIdPInitSLOEnabled()); + statement.setBoolean(QUERY_REQUEST_PROFILE_ENABLED, serviceProviderDO.isAssertionQueryRequestProfileEnabled()); + statement.setBoolean(ECP_ENABLED, serviceProviderDO.isSamlECP()); + statement.setBoolean(ARTIFACT_BINDING_ENABLED, serviceProviderDO.isEnableSAML2ArtifactBinding()); + statement.setBoolean(ARTIFACT_RESOLVE_REQ_SIG_VALIDATION, + serviceProviderDO.isDoValidateSignatureInArtifactResolve()); + statement.setString(IDP_ENTITY_ID_ALIAS, serviceProviderDO.getIdpEntityIDAlias()); + statement.setString(ISSUER_QUALIFIER, serviceProviderDO.getIssuerQualifier()); + statement.setString(SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES, + serviceProviderDO.getSupportedAssertionQueryRequestTypes()); + statement.setTimeStamp(UPDATED_AT, new Timestamp(new Date().getTime()), CALENDAR); + } + + private void setServiceProviderParameters(NamedPreparedStatement statement, + SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws SQLException { + + Timestamp currentTime = new Timestamp(new Date().getTime()); + statement.setInt(TENANT_ID, tenantId); + statement.setString(ISSUER, serviceProviderDO.getIssuer()); + statement.setString(DEFAULT_ASSERTION_CONSUMER_URL, serviceProviderDO.getDefaultAssertionConsumerUrl()); + statement.setString(NAME_ID_FORMAT, serviceProviderDO.getNameIDFormat()); + statement.setString(CERT_ALIAS, serviceProviderDO.getCertAlias()); + statement.setBoolean(REQ_SIG_VALIDATION, serviceProviderDO.isDoValidateSignatureInRequests()); + statement.setBoolean(SIGN_RESPONSE, serviceProviderDO.isDoSignResponse()); + statement.setBoolean(SIGN_ASSERTIONS, serviceProviderDO.isDoSignAssertions()); + statement.setString(SIGNING_ALGO, serviceProviderDO.getSigningAlgorithmUri()); + statement.setString(DIGEST_ALGO, serviceProviderDO.getDigestAlgorithmUri()); + statement.setBoolean(ENCRYPT_ASSERTION, serviceProviderDO.isDoEnableEncryptedAssertion()); + statement.setString(ASSERTION_ENCRYPTION_ALGO, serviceProviderDO.getAssertionEncryptionAlgorithmUri()); + statement.setString(KEY_ENCRYPTION_ALGO, serviceProviderDO.getKeyEncryptionAlgorithmUri()); + statement.setBoolean(ATTR_PROFILE_ENABLED, serviceProviderDO.isEnableAttributesByDefault()); + statement.setString(ATTR_SERVICE_INDEX, serviceProviderDO.getAttributeConsumingServiceIndex()); + statement.setBoolean(SLO_PROFILE_ENABLED, serviceProviderDO.isDoSingleLogout()); + statement.setString(SLO_METHOD, serviceProviderDO.getSingleLogoutMethod()); + statement.setString(SLO_RESPONSE_URL, serviceProviderDO.getSloResponseURL()); + statement.setString(SLO_REQUEST_URL, serviceProviderDO.getSloRequestURL()); + statement.setBoolean(IDP_INIT_SSO_ENABLED, serviceProviderDO.isIdPInitSSOEnabled()); + statement.setBoolean(IDP_INIT_SLO_ENABLED, serviceProviderDO.isIdPInitSLOEnabled()); + statement.setBoolean(QUERY_REQUEST_PROFILE_ENABLED, serviceProviderDO.isAssertionQueryRequestProfileEnabled()); + statement.setBoolean(ECP_ENABLED, serviceProviderDO.isSamlECP()); + statement.setBoolean(ARTIFACT_BINDING_ENABLED, serviceProviderDO.isEnableSAML2ArtifactBinding()); + statement.setBoolean(ARTIFACT_RESOLVE_REQ_SIG_VALIDATION, + serviceProviderDO.isDoValidateSignatureInArtifactResolve()); + statement.setString(IDP_ENTITY_ID_ALIAS, serviceProviderDO.getIdpEntityIDAlias()); + statement.setString(ISSUER_QUALIFIER, serviceProviderDO.getIssuerQualifier()); + statement.setString(SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES, + serviceProviderDO.getSupportedAssertionQueryRequestTypes()); + statement.setString(VERSION, SAML_SCHEMA_VERSION); + statement.setTimeStamp(CREATED_AT, currentTime, CALENDAR); + statement.setTimeStamp(UPDATED_AT, currentTime, CALENDAR); + } + + private int processGetServiceProviderId(String issuer, int tenantId) throws DataAccessException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + Integer serviceProviderId = + namedJdbcTemplate.fetchSingleRecord(SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML_SP_ID_BY_ISSUER, + (resultSet, rowNumber) -> resultSet.getInt(ID), namedPreparedStatement -> { + namedPreparedStatement.setString(ISSUER, issuer); + namedPreparedStatement.setInt(TENANT_ID, tenantId); + }); + if (serviceProviderId == null) { + throw new DataAccessException("No record found for the given issuer: " + issuer); + } + return serviceProviderId.intValue(); + } + + private void processAddServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO,int tenantId) throws DataAccessException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + namedJdbcTemplate.executeInsert(SAMLSSOServiceProviderConstants.SQLQueries.ADD_SAML2_SSO_CONFIG, + namedPreparedStatement -> setServiceProviderParameters(namedPreparedStatement, serviceProviderDO, tenantId), + serviceProviderDO, false); + } + + private void processAddSPProperties(SAMLSSOServiceProviderDO serviceProviderDO, int tenantId) throws DataAccessException { + + List properties = serviceProviderDO.getMultiValuedProperties(); + int serviceProviderId = processGetServiceProviderId(serviceProviderDO.getIssuer(), tenantId); + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + + namedJdbcTemplate.executeBatchInsert(SAMLSSOServiceProviderConstants.SQLQueries.ADD_SAML_SSO_ATTR, + (namedPreparedStatement -> { + for (ServiceProviderProperty property : properties) { + namedPreparedStatement.setInt(SP_ID, serviceProviderId); + namedPreparedStatement.setString(PROPERTY_NAME, property.getKey()); + namedPreparedStatement.setString(PROPERTY_VALUE, property.getValue()); + namedPreparedStatement.addBatch(); + } + }), serviceProviderDO); + } + + private void processUpdateServiceProvider(SAMLSSOServiceProviderDO serviceProviderDO, int serviceProviderId, int tenantId) + throws DataAccessException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + namedJdbcTemplate.executeUpdate(SAMLSSOServiceProviderConstants.SQLQueries.UPDATE_SAML2_SSO_CONFIG, + namedPreparedStatement -> { + namedPreparedStatement.setInt(ID, serviceProviderId); + setUpdateServiceProviderParameters(namedPreparedStatement, serviceProviderDO, tenantId); + }); + } + + private void processUpdateSPProperties(SAMLSSOServiceProviderDO serviceProviderDO, int serviceProviderId) + throws DataAccessException { + + List properties = serviceProviderDO.getMultiValuedProperties(); + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + + namedJdbcTemplate.executeUpdate(SAMLSSOServiceProviderConstants.SQLQueries.DELETE_SAML_SSO_ATTR_BY_ID, + namedPreparedStatement -> namedPreparedStatement.setInt(SP_ID, serviceProviderId)); + + namedJdbcTemplate.executeBatchInsert(SAMLSSOServiceProviderConstants.SQLQueries.ADD_SAML_SSO_ATTR, + (namedPreparedStatement -> { + for (ServiceProviderProperty property : properties) { + namedPreparedStatement.setInt(SP_ID, serviceProviderId); + namedPreparedStatement.setString(PROPERTY_NAME, property.getKey()); + namedPreparedStatement.setString(PROPERTY_VALUE, property.getValue()); + namedPreparedStatement.addBatch(); + } + }), serviceProviderDO); + } + + private SAMLSSOServiceProviderDO processGetServiceProvider(String issuer, int tenantId) throws DataAccessException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + SAMLSSOServiceProviderDO serviceProviderDO = namedJdbcTemplate.fetchSingleRecord( + SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML2_SSO_CONFIG_BY_ISSUER, + (resultSet, rowNumber) -> resourceToObject(resultSet), namedPreparedStatement -> { + namedPreparedStatement.setString(ISSUER, issuer); + namedPreparedStatement.setInt(TENANT_ID, tenantId); + }); + + if (serviceProviderDO != null) { + addProperties(processGetServiceProviderId(issuer, tenantId), serviceProviderDO); + } + return serviceProviderDO; + } + + private List processGetServiceProviders(int tenantId) throws DataAccessException { + + List serviceProvidersList; + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + serviceProvidersList = + namedJdbcTemplate.executeQuery(SAMLSSOServiceProviderConstants.SQLQueries.GET_SAML2_SSO_CONFIGS, + (resultSet, rowNumber) -> resourceToObject(resultSet), + namedPreparedStatement -> namedPreparedStatement.setInt(TENANT_ID, tenantId)); + + for (SAMLSSOServiceProviderDO serviceProviderDO : serviceProvidersList) { + addProperties(processGetServiceProviderId(serviceProviderDO.getIssuer(), tenantId), serviceProviderDO); + } + return serviceProvidersList; + } + + private void processDeleteServiceProvider(String issuer, int tenantId) throws DataAccessException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + + namedJdbcTemplate.executeUpdate(SAMLSSOServiceProviderConstants.SQLQueries.DELETE_SAML2_SSO_CONFIG_BY_ISSUER, + namedPreparedStatement -> { + namedPreparedStatement.setString(ISSUER, issuer); + namedPreparedStatement.setInt(TENANT_ID, tenantId); + }); + + namedJdbcTemplate.executeUpdate(SAMLSSOServiceProviderConstants.SQLQueries.DELETE_SAML_SSO_ATTR, + namedPreparedStatement -> { + namedPreparedStatement.setString(ISSUER, issuer); + namedPreparedStatement.setInt(TENANT_ID, tenantId); + }); + } + + /** + * Returns the {@link java.security.cert.Certificate} which should used to validate the requests + * for the given service provider. + * + * @param serviceProviderDO service provider information object. + * @param tenant tenant Domain. + * @return The X509 certificate used to validate the requests. + * @throws DataAccessException If an error occurs while retrieving the certificate Id. + * @throws CertificateRetrievingException If an error occurs while retrieving the certificate. + */ + private X509Certificate getApplicationCertificate(SAMLSSOServiceProviderDO serviceProviderDO, Tenant tenant) + throws CertificateRetrievingException, DataAccessException { + + // 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 the issuer of the service provider. + * @param tenantId the tenant ID. + * @return the certificate reference ID, or -1 if no certificate is found. + * @throws SQLException + */ + private int getApplicationCertificateId(String issuer, int tenantId) throws DataAccessException { + + NamedJdbcTemplate namedJdbcTemplate = JdbcUtils.getNewNamedJdbcTemplate(); + String sqlStmt = + isH2DB() ? SAMLSSOServiceProviderConstants.SQLQueries.QUERY_TO_GET_APPLICATION_CERTIFICATE_ID_H2 : + SAMLSSOServiceProviderConstants.SQLQueries.QUERY_TO_GET_APPLICATION_CERTIFICATE_ID; + Integer certificateId = + namedJdbcTemplate.fetchSingleRecord(sqlStmt, (resultSet, rowNumber) -> resultSet.getInt(1), + namedPreparedStatement -> { + namedPreparedStatement.setString(1, CERTIFICATE_PROPERTY_NAME); + namedPreparedStatement.setString(2, issuer); + namedPreparedStatement.setInt(3, tenantId); + }); + + return certificateId != null ? certificateId : -1; + } + +} diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/RegistrySAMLSSOServiceProviderDAOImpl.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/RegistrySAMLSSOServiceProviderDAOImpl.java index f07d50eb03b5..109a173bcf33 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/RegistrySAMLSSOServiceProviderDAOImpl.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/dao/RegistrySAMLSSOServiceProviderDAOImpl.java @@ -67,9 +67,10 @@ public class RegistrySAMLSSOServiceProviderDAOImpl extends AbstractDAO getMultiValuedProperties() { + + List multiValuedProperties = new ArrayList<>(); + + // Multi-valued attributes. + getAssertionConsumerUrlList().forEach(assertionConUrl -> + putIfNotNull(multiValuedProperties, MultiValuedPropertyKey.ASSERTION_CONSUMER_URLS.toString(), + assertionConUrl)); + getRequestedRecipientsList().forEach(requestedRecipient -> + putIfNotNull(multiValuedProperties, MultiValuedPropertyKey.RECIPIENTS.toString(), + requestedRecipient)); + getRequestedAudiencesList().forEach(requestedAudience -> + putIfNotNull(multiValuedProperties, MultiValuedPropertyKey.AUDIENCES.toString(), + requestedAudience)); + getIdpInitSLOReturnToURLList().forEach(idpInitSLOReturnToURL -> + putIfNotNull(multiValuedProperties, MultiValuedPropertyKey.SLO_RETURN_TO_URLS.toString(), + idpInitSLOReturnToURL)); + + return multiValuedProperties; + } + + /** + * Add a list of multivalued properties. + * + * @param multiValuedProperties List of ServiceProviderProperty. + */ + public void addMultiValuedProperties(List multiValuedProperties) { + + if (multiValuedProperties == null) { + return; + } + + multiValuedProperties.forEach(this::addMultiValuedProperty); + } + + /** + * Add a multivalued property. + * + * @param multiValuedProperty ServiceProviderProperty. + */ + private void addMultiValuedProperty(ServiceProviderProperty multiValuedProperty) { + + if (multiValuedProperty == null) { + return; + } + String key = multiValuedProperty.getKey(); + String value = multiValuedProperty.getValue(); + + if (MultiValuedPropertyKey.ASSERTION_CONSUMER_URLS.toString().equals(key)) { + List attributeList = getAssertionConsumerUrlList(); + if (attributeList.isEmpty()) { + attributeList = new ArrayList<>(); + } + attributeList.add(value); + setAssertionConsumerUrls(attributeList); + } else if (MultiValuedPropertyKey.RECIPIENTS.toString().equals(key)) { + List attributeList = getRequestedRecipientsList(); + if (attributeList.isEmpty()) { + attributeList = new ArrayList<>(); + } + attributeList.add(value); + setRequestedRecipients(attributeList); + } else if (MultiValuedPropertyKey.AUDIENCES.toString().equals(key)) { + List attributeList = getRequestedAudiencesList(); + if (attributeList.isEmpty()) { + attributeList = new ArrayList<>(); + } + attributeList.add(value); + setRequestedAudiences(attributeList); + } else if (MultiValuedPropertyKey.SLO_RETURN_TO_URLS.toString().equals(key)) { + List attributeList = getIdpInitSLOReturnToURLList(); + if (attributeList.isEmpty()) { + attributeList = new ArrayList<>(); + } + attributeList.add(value); + setIdpInitSLOReturnToURLs(attributeList); + } + } + + /** + * Put a key value pair to a list if the value is not null. + * + * @param list List of ServiceProviderProperty. + * @param key Key. + * @param value Value. + */ + private void putIfNotNull(List list, String key, String value) { + + if (StringUtils.isNotBlank(value)) { + list.add(new ServiceProviderProperty(key, value)); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SAMLSSOServiceProviderDO that = (SAMLSSOServiceProviderDO) o; + return doSingleLogout == that.doSingleLogout && + doSignResponse == that.doSignResponse && + doSignAssertions == that.doSignAssertions && + enableAttributesByDefault == that.enableAttributesByDefault && + isIdPInitSSOEnabled == that.isIdPInitSSOEnabled && + idPInitSLOEnabled == that.idPInitSLOEnabled && + doEnableEncryptedAssertion == that.doEnableEncryptedAssertion && + doValidateSignatureInRequests == that.doValidateSignatureInRequests && + doValidateSignatureInArtifactResolve == that.doValidateSignatureInArtifactResolve && + enableSAML2ArtifactBinding == that.enableSAML2ArtifactBinding && + samlECP == that.samlECP && + doFrontChannelLogout == that.doFrontChannelLogout && + Objects.equals(tenantDomain, that.tenantDomain) && + Objects.equals(issuer, that.issuer) && + Objects.equals(issuerQualifier, that.issuerQualifier) && + Objects.equals(assertionConsumerUrl, that.assertionConsumerUrl) && + Arrays.equals(assertionConsumerUrls, that.assertionConsumerUrls) && + Objects.equals(defaultAssertionConsumerUrl, that.defaultAssertionConsumerUrl) && + Objects.equals(certAlias, that.certAlias) && + Objects.equals(sloResponseURL, that.sloResponseURL) && + Objects.equals(sloRequestURL, that.sloRequestURL) && + Objects.equals(loginPageURL, that.loginPageURL) && + Objects.equals(attributeConsumingServiceIndex, that.attributeConsumingServiceIndex) && + Arrays.equals(requestedClaims, that.requestedClaims) && + Arrays.equals(requestedAudiences, that.requestedAudiences) && + Arrays.equals(requestedRecipients, that.requestedRecipients) && + Objects.equals(nameIdClaimUri, that.nameIdClaimUri) && + Objects.equals(nameIDFormat, that.nameIDFormat) && + Arrays.equals(idpInitSLOReturnToURLs, that.idpInitSLOReturnToURLs) && + Objects.equals(signingAlgorithmUri, that.signingAlgorithmUri) && + Objects.equals(digestAlgorithmUri, that.digestAlgorithmUri) && + Objects.equals(assertionEncryptionAlgorithmUri, that.assertionEncryptionAlgorithmUri) && + Objects.equals(keyEncryptionAlgorithmUri, that.keyEncryptionAlgorithmUri) && + Objects.equals(signingCertificate, that.signingCertificate) && + Objects.equals(encryptionCertificate, that.encryptionCertificate) && + Objects.equals(idpEntityIDAlias, that.idpEntityIDAlias) && + Objects.equals(frontChannelLogoutBinding, that.frontChannelLogoutBinding); + } + + @Override + public int hashCode() { + + int h = Objects.hash(tenantDomain, issuer, issuerQualifier, assertionConsumerUrl, defaultAssertionConsumerUrl, + certAlias, sloResponseURL, sloRequestURL, doSingleLogout, loginPageURL, doSignResponse, + doSignAssertions, attributeConsumingServiceIndex, enableAttributesByDefault, nameIdClaimUri, + nameIDFormat, isIdPInitSSOEnabled, idPInitSLOEnabled, doEnableEncryptedAssertion, + doValidateSignatureInRequests, doValidateSignatureInArtifactResolve, signingAlgorithmUri, + digestAlgorithmUri, assertionEncryptionAlgorithmUri, keyEncryptionAlgorithmUri, signingCertificate, + encryptionCertificate, isAssertionQueryRequestProfileEnabled, supportedAssertionQueryRequestTypes, + enableSAML2ArtifactBinding, samlECP, idpEntityIDAlias, doFrontChannelLogout, frontChannelLogoutBinding); + h = 31 * h + Arrays.hashCode(assertionConsumerUrls); + h = 31 * h + Arrays.hashCode(requestedClaims); + h = 31 * h + Arrays.hashCode(requestedAudiences); + h = 31 * h + Arrays.hashCode(requestedRecipients); + h = 31 * h + Arrays.hashCode(idpInitSLOReturnToURLs); + return h; + } } diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/model/ServiceProviderProperty.java b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/model/ServiceProviderProperty.java new file mode 100644 index 000000000000..5d2fadf6aff8 --- /dev/null +++ b/components/identity-core/org.wso2.carbon.identity.core/src/main/java/org/wso2/carbon/identity/core/model/ServiceProviderProperty.java @@ -0,0 +1,53 @@ +/* + * 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.model; + +/** + * Represents a service provider property with a key-value pair storing ASSERTION_CONSUMER_URLS, AUDIENCES, RECIPIENTS, + * SLO_RETURN_TO_URLS properties for a service provider. + */ +public class ServiceProviderProperty { + + private String key; + private String value; + + public ServiceProviderProperty(String key, String value) { + this.key = key; + this.value = value; + } + + /** + * Get the key of the tuple. + * + * @return Key of the tuple. + */ + public String getKey() { + return this.key; + } + + /** + * Get the value of the tuple. + * + * @return Value of the tuple. + */ + public String getValue() { + return this.value; + } + +} diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManagerTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManagerTest.java new file mode 100644 index 000000000000..48f422e68400 --- /dev/null +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/SAMLSSOServiceProviderManagerTest.java @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2024, 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; + +import org.apache.commons.lang.StringUtils; +import org.mockito.MockedStatic; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate; +import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; +import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException; +import org.wso2.carbon.identity.base.IdentityException; +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.identity.core.util.IdentityUtil; +import org.wso2.carbon.identity.core.util.JdbcUtils; +import org.wso2.carbon.identity.core.util.TestUtils; + +import java.sql.Connection; + +import javax.sql.DataSource; + +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.lenient; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.testng.Assert.assertEquals; + +import static org.testng.Assert.assertTrue; +import static org.wso2.carbon.identity.core.constant.TestConstants.*; +import static org.mockito.ArgumentMatchers.any; + +/** + * This class tests the methods of the SAMLSSOServiceProviderManager class. + */ +@Listeners(MockitoTestNGListener.class) +public class SAMLSSOServiceProviderManagerTest { + + private MockedStatic identityUtil; + private MockedStatic identityTenantUtil; + private MockedStatic identityDatabaseUtil; + + public SAMLSSOServiceProviderManager samlSSOServiceProviderManager; + + public SAMLSSOServiceProviderDO sampleServiceProvider1; + public SAMLSSOServiceProviderDO sampleServiceProvider2; + public SAMLSSOServiceProviderDO invalidServiceProviderDO; + + @BeforeMethod + public void setUp() throws Exception { + + samlSSOServiceProviderManager = new SAMLSSOServiceProviderManager(); + sampleServiceProvider1 = createServiceProviderDO(ISSUER1); + sampleServiceProvider2 = createServiceProviderDO(ISSUER2); + invalidServiceProviderDO = createServiceProviderDO(null); + + TestUtils.initiateH2Base(); + DataSource dataSource = mock(DataSource.class); + identityDatabaseUtil = mockStatic(IdentityDatabaseUtil.class); + identityUtil = mockStatic(IdentityUtil.class); + identityTenantUtil = mockStatic(IdentityTenantUtil.class); + + identityUtil.when(() -> IdentityUtil.getProperty("SAMLStorage.Type")).thenReturn("database"); + identityDatabaseUtil.when(IdentityDatabaseUtil::getDataSource).thenReturn(dataSource); + + Connection connection = TestUtils.getConnection(); + Connection spyConnection = TestUtils.spyConnection(connection); + + lenient().when(dataSource.getConnection()).thenReturn(spyConnection); + lenient().doNothing().when(spyConnection).close(); + + } + + @AfterMethod + public void tearDown() throws Exception { + + identityUtil.close(); + identityTenantUtil.close(); + identityDatabaseUtil.close(); + TestUtils.closeH2Base(); + } + + @Test + public void testAddServiceProvider() throws Exception { + + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + SAMLSSOServiceProviderDO serviceProviderFromStorage = + samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID); + assertEquals(serviceProviderFromStorage, sampleServiceProvider1); + } + + @Test + public void testAddEmptyServiceProvider() { + + assertThrows(IdentityException.class, + () -> samlSSOServiceProviderManager.addServiceProvider(invalidServiceProviderDO, TENANT_ID)); + } + + @Test + public void addServiceProviderWithDuplicateIssuer() throws Exception { + + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + System.out.println("sampleServiceProvider iss " + sampleServiceProvider1); + assertFalse(samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID)); + } + + @Test + public void testAddServiceProviderWithException() throws Exception { + + SAMLSSOServiceProviderDO serviceProviderDO = createServiceProviderDO(ISSUER1); + + try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) { + NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class); + jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate); + doThrow(new TransactionException("Transaction failed")).when(namedJdbcTemplate).withTransaction(any()); + + assertThrows(IdentityException.class, + () -> samlSSOServiceProviderManager.addServiceProvider(serviceProviderDO, TENANT_ID)); + } + } + + @Test + public void testUpdateServiceProvider() throws Exception { + + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + sampleServiceProvider1.setDoSingleLogout(UPDATED_DO_SINGLE_LOGOUT); + sampleServiceProvider1.setRequestedRecipients(UPDATED_REQUESTED_RECIPIENTS); + + samlSSOServiceProviderManager.updateServiceProvider(sampleServiceProvider1, getIssuerWithQualifier(ISSUER1), + TENANT_ID); + + SAMLSSOServiceProviderDO updatedServiceProvider = + samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID); + assertEquals(sampleServiceProvider1, updatedServiceProvider); + } + + @Test + public void testUpdateServiceProviderWithDuplicateIssuer() throws Exception { + + sampleServiceProvider1 = createServiceProviderDO(ISSUER1); + sampleServiceProvider2 = createServiceProviderDO(ISSUER2); + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider2, TENANT_ID); + + sampleServiceProvider2.setIssuer(getIssuerWithQualifier(ISSUER1)); + assertFalse(samlSSOServiceProviderManager.updateServiceProvider(sampleServiceProvider2, ISSUER2, TENANT_ID)); + } + + @Test + public void testUpdateWithInvalidServiceProvider() throws Exception { + + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + assertThrows(IdentityException.class, + () -> samlSSOServiceProviderManager.updateServiceProvider(invalidServiceProviderDO, + getIssuerWithQualifier(ISSUER1), TENANT_ID)); + } + + @Test + public void testUpdateServiceProviderWithException() throws Exception { + + SAMLSSOServiceProviderDO serviceProviderDO = createServiceProviderDO(ISSUER1); + + try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) { + NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class); + jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate); + lenient().doThrow(new TransactionException("Transaction failed")).when(namedJdbcTemplate) + .withTransaction(any()); + + assertThrows(IdentityException.class, + () -> samlSSOServiceProviderManager.updateServiceProvider(serviceProviderDO, + getIssuerWithQualifier(ISSUER1), TENANT_ID)); + } + } + + @Test + public void testGetServiceProviders() throws Exception { + + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + sampleServiceProvider2 = createServiceProviderDO(ISSUER2); + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider2, TENANT_ID); + + SAMLSSOServiceProviderDO[] serviceProviders = samlSSOServiceProviderManager.getServiceProviders(TENANT_ID); + + assertEquals(serviceProviders, new SAMLSSOServiceProviderDO[]{sampleServiceProvider1, sampleServiceProvider2}); + } + + @Test + public void testGetServiceProvidersWithDataAccessException() throws Exception { + + try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) { + NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class); + jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate); + doThrow(new DataAccessException("Data access error")).when(namedJdbcTemplate) + .executeQuery(any(), any(), any()); + + assertThrows(IdentityException.class, () -> samlSSOServiceProviderManager.getServiceProviders(TENANT_ID)); + } + } + + @Test + public void testGetServiceProvider() throws Exception { + + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + + SAMLSSOServiceProviderDO serviceProviderFromStorage = + samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID); + + assertEquals(serviceProviderFromStorage, sampleServiceProvider1); + } + + @Test + public void testProcessGetServiceProviderWithDataAccessException() throws Exception { + + try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) { + NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class); + jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate); + doThrow(new DataAccessException("Data access error")).when(namedJdbcTemplate) + .fetchSingleRecord(any(), any(), any()); + + assertThrows(IdentityException.class, + () -> samlSSOServiceProviderManager.getServiceProvider(ISSUER1, TENANT_ID)); + } + } + + @Test + public void testIsServiceProviderExists() throws Exception { + + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + assertTrue(samlSSOServiceProviderManager.isServiceProviderExists(getIssuerWithQualifier(ISSUER1), TENANT_ID)); + } + + @Test + public void testNonExistingIsServiceProviderExists() throws Exception { + + assertFalse(samlSSOServiceProviderManager.isServiceProviderExists(getIssuerWithQualifier(ISSUER1), TENANT_ID)); + } + + @Test + public void testRemoveServiceProvider() throws Exception { + + samlSSOServiceProviderManager.addServiceProvider(sampleServiceProvider1, TENANT_ID); + assertTrue(samlSSOServiceProviderManager.removeServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID)); + assertNull(samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID)); + + } + + @Test + public void testRemoveNonExistingServiceProvider() throws Exception { + + assertFalse(samlSSOServiceProviderManager.removeServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID)); + } + + @Test + public void testRemoveEmptyServiceProvider() { + + assertThrows(IllegalArgumentException.class, + () -> samlSSOServiceProviderManager.removeServiceProvider(null, TENANT_ID)); + } + + @Test + public void testUploadServiceProvider() throws Exception { + + samlSSOServiceProviderManager.uploadServiceProvider(sampleServiceProvider1, TENANT_ID); + + SAMLSSOServiceProviderDO serviceProviderFromStorage = + samlSSOServiceProviderManager.getServiceProvider(getIssuerWithQualifier(ISSUER1), TENANT_ID); + assertEquals(serviceProviderFromStorage, sampleServiceProvider1); + } + + @Test + public void testUploadDuplicateServiceProvider() throws Exception { + + samlSSOServiceProviderManager.uploadServiceProvider(sampleServiceProvider1, TENANT_ID); + assertThrows(IdentityException.class, + () -> samlSSOServiceProviderManager.uploadServiceProvider(sampleServiceProvider1, TENANT_ID)); + } + + @Test + public void testUploadServiceProviderWithDataAccessException() throws Exception { + + SAMLSSOServiceProviderDO serviceProviderDO = createServiceProviderDO(ISSUER1); + + try (MockedStatic jdbcUtilsMockedStatic = mockStatic(JdbcUtils.class)) { + NamedJdbcTemplate namedJdbcTemplate = mock(NamedJdbcTemplate.class); + jdbcUtilsMockedStatic.when(JdbcUtils::getNewNamedJdbcTemplate).thenReturn(namedJdbcTemplate); + doThrow(new DataAccessException("Data access error")).when(namedJdbcTemplate).withTransaction(any()); + + assertThrows(IdentityException.class, + () -> samlSSOServiceProviderManager.uploadServiceProvider(serviceProviderDO, TENANT_ID)); + } + } + + private SAMLSSOServiceProviderDO createServiceProviderDO(String issuer) { + + SAMLSSOServiceProviderDO serviceProviderDO = new SAMLSSOServiceProviderDO(); + serviceProviderDO.setIssuer(issuer); + serviceProviderDO.setIssuerQualifier(ISSUER_QUALIFIER); + serviceProviderDO.setAssertionConsumerUrls(ASSERTION_CONSUMER_URLS); + serviceProviderDO.setDefaultAssertionConsumerUrl(DEFAULT_ASSERTION_CONSUMER_URL); + serviceProviderDO.setCertAlias(CERT_ALIAS); + serviceProviderDO.setSloResponseURL(SLO_RESPONSE_URL); + serviceProviderDO.setSloRequestURL(SLO_REQUEST_URL); + serviceProviderDO.setDoSingleLogout(DO_SINGLE_LOGOUT); + serviceProviderDO.setDoSignResponse(DO_SIGN_RESPONSE); + serviceProviderDO.setDoSignAssertions(DO_SIGN_ASSERTIONS); + serviceProviderDO.setAttributeConsumingServiceIndex(ATTRIBUTE_CONSUMING_SERVICE_INDEX); + serviceProviderDO.setRequestedAudiences(REQUESTED_AUDIENCES); + serviceProviderDO.setRequestedRecipients(REQUESTED_RECIPIENTS); + serviceProviderDO.setEnableAttributesByDefault(ENABLE_ATTRIBUTES_BY_DEFAULT); + serviceProviderDO.setNameIDFormat(NAME_ID_FORMAT); + serviceProviderDO.setIdPInitSSOEnabled(IS_IDP_INIT_SSO_ENABLED); + serviceProviderDO.setIdPInitSLOEnabled(IDP_INIT_SLO_ENABLED); + serviceProviderDO.setIdpInitSLOReturnToURLs(IDP_INIT_SLO_RETURN_TO_URLS); + serviceProviderDO.setDoEnableEncryptedAssertion(DO_ENABLE_ENCRYPTED_ASSERTION); + serviceProviderDO.setDoValidateSignatureInRequests(DO_VALIDATE_SIGNATURE_IN_REQUESTS); + serviceProviderDO.setDoValidateSignatureInArtifactResolve(DO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE); + serviceProviderDO.setSigningAlgorithmUri(SIGNING_ALGORITHM_URI); + serviceProviderDO.setDigestAlgorithmUri(DIGEST_ALGORITHM_URI); + serviceProviderDO.setAssertionEncryptionAlgorithmUri(ASSERTION_ENCRYPTION_ALGORITHM_URI); + serviceProviderDO.setKeyEncryptionAlgorithmUri(KEY_ENCRYPTION_ALGORITHM_URI); + serviceProviderDO.setAssertionQueryRequestProfileEnabled(IS_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED); + serviceProviderDO.setSupportedAssertionQueryRequestTypes(SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES); + serviceProviderDO.setEnableSAML2ArtifactBinding(ENABLE_SAML2_ARTIFACT_BINDING); + serviceProviderDO.setSamlECP(SAML_ECP); + serviceProviderDO.setIdpEntityIDAlias(IDP_ENTITY_ID_ALIAS); + serviceProviderDO.setDoFrontChannelLogout(DO_FRONT_CHANNEL_LOGOUT); + serviceProviderDO.setFrontChannelLogoutBinding(FRONT_CHANNEL_LOGOUT_BINDING); + + return serviceProviderDO; + } + + public String getIssuerWithQualifier(String issuer) { + + return StringUtils.isNotBlank(ISSUER_QUALIFIER) ? + issuer + IdentityRegistryResources.QUALIFIER_ID + ISSUER_QUALIFIER : issuer; + } +} diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/constant/TestConstants.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/constant/TestConstants.java new file mode 100644 index 000000000000..2d0cf51c10a6 --- /dev/null +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/constant/TestConstants.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024, 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.constant; + +/** + * Test constants for SAMLSSOServiceProvider tests. + */ +public class TestConstants { + + public static final int TENANT_ID = 1; + public static final String ISSUER1 = "issuer1"; + public static final String ISSUER2 = "issuer2"; + public static final String ISSUER_QUALIFIER = "issuerQualifier"; + public static final String[] ASSERTION_CONSUMER_URLS = {"http://localhost:8080/acs", "http://localhost:8080/acs1"}; + public static final String DEFAULT_ASSERTION_CONSUMER_URL = "http://localhost:8080/acs"; + public static final String CERT_ALIAS = "wso2carbon"; + public static final String SLO_RESPONSE_URL = "http://localhost:8080/sloResponse"; + public static final String SLO_REQUEST_URL = "http://localhost:8080/sloRequest"; + public static final boolean DO_SINGLE_LOGOUT = true; + public static final boolean DO_SIGN_RESPONSE = true; + public static final boolean DO_SIGN_ASSERTIONS = true; + public static final String ATTRIBUTE_CONSUMING_SERVICE_INDEX = "index"; + public static final String[] REQUESTED_AUDIENCES = {"audience1", "audience2"}; + public static final String[] REQUESTED_RECIPIENTS = {"recipient1", "recipient2"}; + public static final boolean ENABLE_ATTRIBUTES_BY_DEFAULT = true; + public static final String NAME_ID_FORMAT = "nameIDFormat"; + public static final boolean IS_IDP_INIT_SSO_ENABLED = true; + public static final boolean IDP_INIT_SLO_ENABLED = true; + public static final String[] IDP_INIT_SLO_RETURN_TO_URLS = + {"http://localhost:8080/returnTo1", "http://localhost:8080/returnTo2"}; + public static final boolean DO_ENABLE_ENCRYPTED_ASSERTION = false; + public static final boolean DO_VALIDATE_SIGNATURE_IN_REQUESTS = false; + public static final boolean DO_VALIDATE_SIGNATURE_IN_ARTIFACT_RESOLVE = false; + public static final String SIGNING_ALGORITHM_URI = "signingAlgorithmUri"; + public static final String DIGEST_ALGORITHM_URI = "digestAlgorithmUri"; + public static final String ASSERTION_ENCRYPTION_ALGORITHM_URI = "assertionEncryptionAlgorithmUri"; + public static final String KEY_ENCRYPTION_ALGORITHM_URI = "keyEncryptionAlgorithmUri"; + public static final boolean IS_ASSERTION_QUERY_REQUEST_PROFILE_ENABLED = true; + public static final String SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES = "supportedTypes"; + public static final boolean ENABLE_SAML2_ARTIFACT_BINDING = true; + public static final boolean SAML_ECP = true; + public static final String IDP_ENTITY_ID_ALIAS = "idpEntityIDAlias"; + public static final boolean DO_FRONT_CHANNEL_LOGOUT = true; + public static final String FRONT_CHANNEL_LOGOUT_BINDING = "frontChannelLogoutBinding"; + + public static final boolean UPDATED_DO_SINGLE_LOGOUT = false; + public static final String[] UPDATED_REQUESTED_RECIPIENTS = {"updatedRecipient1", "updatedRecipient2"}; +} 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 6b3636f4744a..a298e8a566eb 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 @@ -64,6 +64,7 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; +import static org.wso2.carbon.identity.core.constant.TestConstants.TENANT_ID; /** * Test class for SAMLSSOServiceProviderDAO. @@ -80,7 +81,6 @@ public class SAMLSSOServiceProviderDAOTest { private Map> dummyPropertiesWithAnIssuerQualifier; private MockedStatic transaction; private MockedStatic identityTenantUtil; - private static final int TENANT_ID = 1; @BeforeMethod public void setUp() throws Exception { diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLServiceProviderPersistenceManagerFactoryTest.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLServiceProviderPersistenceManagerFactoryTest.java index 0df52c6d7ad2..a217b1aa387c 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLServiceProviderPersistenceManagerFactoryTest.java +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/dao/SAMLServiceProviderPersistenceManagerFactoryTest.java @@ -26,6 +26,9 @@ import static org.testng.Assert.assertTrue; +/** + * This class tests the methods of the SAMLServiceProviderPersistenceManagerFactory class. + */ public class SAMLServiceProviderPersistenceManagerFactoryTest { private SAMLServiceProviderPersistenceManagerFactory factory; @@ -49,7 +52,7 @@ public void testGetSAMLServiceProviderPersistenceManagerWithDefaultStorage() thr setPrivateStaticField(SAMLServiceProviderPersistenceManagerFactory.class, "SAML_STORAGE_TYPE", "database"); SAMLSSOServiceProviderDAO samlSSOServiceProviderDAO = factory.getSAMLServiceProviderPersistenceManager(); -// assertTrue(samlSSOServiceProviderDAO instanceof JDBCSAMLSSOServiceProviderDAOImpl); + assertTrue(samlSSOServiceProviderDAO instanceof JDBCSAMLSSOServiceProviderDAOImpl); } @Test @@ -63,9 +66,10 @@ public void testGetSAMLServiceProviderPersistenceManagerWithRegistryStorage() th @Test public void testGetSAMLServiceProviderPersistenceManagerWithHybridStorage() throws Exception { + //TODO : Change test to check for HybridSAMLSSOServiceProviderDAOImpl once implemented. setPrivateStaticField(SAMLServiceProviderPersistenceManagerFactory.class, "SAML_STORAGE_TYPE", "hybrid"); SAMLSSOServiceProviderDAO samlSSOServiceProviderDAO = factory.getSAMLServiceProviderPersistenceManager(); -// assertTrue(samlSSOServiceProviderDAO instanceof JDBCSAMLSSOServiceProviderDAOImpl); + assertTrue(samlSSOServiceProviderDAO instanceof JDBCSAMLSSOServiceProviderDAOImpl); } private void setPrivateStaticField(Class clazz, String fieldName, Object newValue) diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/TestUtils.java b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/TestUtils.java new file mode 100644 index 000000000000..7d0c9fe1b252 --- /dev/null +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/java/org/wso2/carbon/identity/core/util/TestUtils.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, 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.util; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.lang.StringUtils; + +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.Mockito.spy; + +/** + * Utility functions for testing SAMLSSOServiceProviderManager class. + */ +public class TestUtils { + + public static final String DB_NAME = "SAMLSSOServiceProviderManagerDB"; + public static final String H2_SCRIPT_NAME = "h2.sql"; + public static Map dataSourceMap = new HashMap<>(); + + public static Connection spyConnection(Connection connection) throws SQLException { + + Connection spy = spy(connection); + return spy; + } + + public static String getFilePath(String fileName) { + + if (StringUtils.isNotBlank(fileName)) { + return Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "dbscripts", fileName) + .toString(); + } + throw new IllegalArgumentException("DB Script file name cannot be empty."); + } + + public static void initiateH2Base() throws Exception { + + BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUsername("username"); + dataSource.setPassword("password"); + dataSource.setUrl("jdbc:h2:mem:test" + DB_NAME); + try (Connection connection = dataSource.getConnection()) { + connection.createStatement().executeUpdate("DROP ALL OBJECTS"); + connection.createStatement().executeUpdate("RUNSCRIPT FROM '" + getFilePath(H2_SCRIPT_NAME) + "'"); + } + dataSourceMap.put(DB_NAME, dataSource); + } + + public static void closeH2Base() throws Exception { + + BasicDataSource dataSource = dataSourceMap.get(DB_NAME); + if (dataSource != null) { + dataSource.close(); + } + } + + public static Connection getConnection() throws SQLException { + + if (dataSourceMap.get(DB_NAME) != null) { + return dataSourceMap.get(DB_NAME).getConnection(); + } + throw new RuntimeException("No data source initiated for database: " + DB_NAME); + } + +} diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/dbscripts/h2.sql b/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/dbscripts/h2.sql new file mode 100644 index 000000000000..224c8e2144ae --- /dev/null +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/dbscripts/h2.sql @@ -0,0 +1,49 @@ +CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL AUTO_INCREMENT, + ISSUER VARCHAR(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR(255) NOT NULL, + CERT_ALIAS VARCHAR(255), + REQ_SIG_VALIDATION BOOLEAN, + SIGN_RESPONSE BOOLEAN NOT NULL, + SIGN_ASSERTIONS BOOLEAN NOT NULL, + SIGNING_ALGO VARCHAR(255) NOT NULL, + DIGEST_ALGO VARCHAR(255) NOT NULL, + ENCRYPT_ASSERTION BOOLEAN, + ASSERTION_ENCRYPTION_ALGO VARCHAR(255), + KEY_ENCRYPTION_ALGO VARCHAR(255), + ATTR_PROFILE_ENABLED BOOLEAN NOT NULL, + ATTR_SERVICE_INDEX VARCHAR(255), + SLO_PROFILE_ENABLED BOOLEAN NOT NULL, + SLO_METHOD VARCHAR(255), + SLO_RESPONSE_URL VARCHAR(2048), + SLO_REQUEST_URL VARCHAR(2048), + IDP_INIT_SSO_ENABLED BOOLEAN, + IDP_INIT_SLO_ENABLED BOOLEAN, + QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL, + ECP_ENABLED BOOLEAN NOT NULL, + ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN, + IDP_ENTITY_ID_ALIAS VARCHAR(255), + ISSUER_QUALIFIER VARCHAR(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT DATETIME NOT NULL, + UPDATED_AT DATETIME NOT NULL, + PRIMARY KEY (ID) +); + +CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + PROPERTY_NAME VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE +); + +--SAML-- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); diff --git a/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/testng.xml b/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/testng.xml index 086c07b39dae..fa65ac76205f 100644 --- a/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/testng.xml +++ b/components/identity-core/org.wso2.carbon.identity.core/src/test/resources/testng.xml @@ -26,6 +26,7 @@ + diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql index b029ed8dd200..c6743bb97bea 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/db2.sql @@ -1836,6 +1836,73 @@ CREATE TABLE IDN_OAUTH_PAR ( PARAMETERS CLOB(1M) ) / +CREATE TABLE IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL, + ISSUER VARCHAR(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR(255) NOT NULL, + CERT_ALIAS VARCHAR(255), + REQ_SIG_VALIDATION CHAR(1), + SIGN_RESPONSE CHAR(1) NOT NULL, + SIGN_ASSERTIONS CHAR(1) NOT NULL, + SIGNING_ALGO VARCHAR(255) NOT NULL, + DIGEST_ALGO VARCHAR(255) NOT NULL, + ENCRYPT_ASSERTION CHAR(1), + ASSERTION_ENCRYPTION_ALGO VARCHAR(255), + KEY_ENCRYPTION_ALGO VARCHAR(255), + ATTR_PROFILE_ENABLED CHAR(1) NOT NULL, + ATTR_SERVICE_INDEX VARCHAR(255), + SLO_PROFILE_ENABLED CHAR(1) NOT NULL, + SLO_METHOD VARCHAR(255), + SLO_RESPONSE_URL VARCHAR(2048), + SLO_REQUEST_URL VARCHAR(2048), + IDP_INIT_SSO_ENABLED CHAR(1), + IDP_INIT_SLO_ENABLED CHAR(1), + QUERY_REQUEST_PROFILE_ENABLED CHAR(1) NOT NULL, + ECP_ENABLED CHAR(1) NOT NULL, + ARTIFACT_BINDING_ENABLED CHAR(1) NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION CHAR(1), + IDP_ENTITY_ID_ALIAS VARCHAR(255), + ISSUER_QUALIFIER VARCHAR(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, + PRIMARY KEY (ID) +) +/ +CREATE SEQUENCE IDN_SAML2_SERVICE_PROVIDER_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE TRIGGER IDN_SAML2_SERVICE_PROVIDER_TRIG NO CASCADE + BEFORE INSERT + ON IDN_SAML2_SERVICE_PROVIDER + REFERENCING NEW AS NEW + FOR EACH ROW MODE DB2SQL + BEGIN ATOMIC + SET (NEW.ID) = (NEXTVAL FOR IDN_SAML2_SERVICE_PROVIDER_SEQ); + END +/ +CREATE TABLE IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL, + PROPERTY_NAME VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER(ID) ON DELETE CASCADE +) +/ +CREATE SEQUENCE IDN_SAML2_SP_PROPERTIES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE TRIGGER IDN_SAML2_SP_PROPERTIES_TRIG NO CASCADE + BEFORE INSERT + ON IDN_SAML2_SP_PROPERTIES + REFERENCING NEW AS NEW + FOR EACH ROW MODE DB2SQL + BEGIN ATOMIC + SET (NEW.ID) = (NEXTVAL FOR IDN_SAML2_SP_PROPERTIES_SEQ); + END +/ CREATE TABLE IDN_ORG_USER_INVITATION ( ID INTEGER NOT NULL, @@ -2327,3 +2394,11 @@ CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID) / CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID) / + +--SAML-- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +/ +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +/ +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); +/ diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql index 56f35ea09d30..f1deb2ed35f9 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/h2.sql @@ -1220,6 +1220,51 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH_PAR ( PARAMETERS MEDIUMTEXT ); +CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL AUTO_INCREMENT, + ISSUER VARCHAR(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR(255) NOT NULL, + CERT_ALIAS VARCHAR(255), + REQ_SIG_VALIDATION BOOLEAN, + SIGN_RESPONSE BOOLEAN NOT NULL, + SIGN_ASSERTIONS BOOLEAN NOT NULL, + SIGNING_ALGO VARCHAR(255) NOT NULL, + DIGEST_ALGO VARCHAR(255) NOT NULL, + ENCRYPT_ASSERTION BOOLEAN, + ASSERTION_ENCRYPTION_ALGO VARCHAR(255), + KEY_ENCRYPTION_ALGO VARCHAR(255), + ATTR_PROFILE_ENABLED BOOLEAN NOT NULL, + ATTR_SERVICE_INDEX VARCHAR(255), + SLO_PROFILE_ENABLED BOOLEAN NOT NULL, + SLO_METHOD VARCHAR(255), + SLO_RESPONSE_URL VARCHAR(2048), + SLO_REQUEST_URL VARCHAR(2048), + IDP_INIT_SSO_ENABLED BOOLEAN, + IDP_INIT_SLO_ENABLED BOOLEAN, + QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL, + ECP_ENABLED BOOLEAN NOT NULL, + ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN, + IDP_ENTITY_ID_ALIAS VARCHAR(255), + ISSUER_QUALIFIER VARCHAR(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT DATETIME NOT NULL, + UPDATED_AT DATETIME NOT NULL, + PRIMARY KEY (ID) +); + +CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + PROPERTY_NAME VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE +); + CREATE TABLE IF NOT EXISTS IDN_ORG_USER_INVITATION ( ID INTEGER NOT NULL AUTO_INCREMENT, INVITATION_ID VARCHAR(40) NOT NULL, @@ -1526,3 +1571,8 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); -- RULES -- CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + +-- SAML -- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql index 199d5d9d2404..8b0977d4c591 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mssql.sql @@ -1355,6 +1355,53 @@ CREATE TABLE IDN_OAUTH_PAR ( PRIMARY KEY (REQ_URI_REF) ); +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_SAML2_SERVICE_PROVIDER]') AND TYPE IN (N'U')) +CREATE TABLE IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL IDENTITY, + ISSUER VARCHAR(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR(255) NOT NULL, + CERT_ALIAS VARCHAR(255), + REQ_SIG_VALIDATION BIT, + SIGN_RESPONSE BIT NOT NULL, + SIGN_ASSERTIONS BIT NOT NULL, + SIGNING_ALGO VARCHAR(255) NOT NULL, + DIGEST_ALGO VARCHAR(255) NOT NULL, + ENCRYPT_ASSERTION BIT, + ASSERTION_ENCRYPTION_ALGO VARCHAR(255), + KEY_ENCRYPTION_ALGO VARCHAR(255), + ATTR_PROFILE_ENABLED BIT NOT NULL, + ATTR_SERVICE_INDEX VARCHAR(255), + SLO_PROFILE_ENABLED BIT NOT NULL, + SLO_METHOD VARCHAR(255), + SLO_RESPONSE_URL VARCHAR(2048), + SLO_REQUEST_URL VARCHAR(2048), + IDP_INIT_SSO_ENABLED BIT, + IDP_INIT_SLO_ENABLED BIT, + QUERY_REQUEST_PROFILE_ENABLED BIT NOT NULL, + ECP_ENABLED BIT NOT NULL, + ARTIFACT_BINDING_ENABLED BIT NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BIT, + IDP_ENTITY_ID_ALIAS VARCHAR(255), + ISSUER_QUALIFIER VARCHAR(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT DATETIME NOT NULL, + UPDATED_AT DATETIME NOT NULL, + PRIMARY KEY (ID) +); + +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_SAML2_SP_PROPERTIES]') AND TYPE IN (N'U')) +CREATE TABLE IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL IDENTITY, + PROPERTY_NAME VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE +); + IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[IDN_ORG_USER_INVITATION]') AND TYPE IN (N'U')) CREATE TABLE IDN_ORG_USER_INVITATION ( ID INTEGER IDENTITY(1,1) NOT NULL, @@ -1680,6 +1727,11 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); +-- SAML -- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); + GO -- Trigger IDN_CLAIM delete by dialect on IDN_CLAIM_DIALECT deletion -- diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql index e53f3c0f542f..4e9e391a43c2 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql-cluster.sql @@ -1382,6 +1382,51 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH_PAR ( PARAMETERS MEDIUMTEXT ) ENGIN NDB; +CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL AUTO_INCREMENT, + ISSUER VARCHAR(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR(255) NOT NULL, + CERT_ALIAS VARCHAR(255), + REQ_SIG_VALIDATION BOOLEAN, + SIGN_RESPONSE BOOLEAN NOT NULL, + SIGN_ASSERTIONS BOOLEAN NOT NULL, + SIGNING_ALGO VARCHAR(255) NOT NULL, + DIGEST_ALGO VARCHAR(255) NOT NULL, + ENCRYPT_ASSERTION BOOLEAN, + ASSERTION_ENCRYPTION_ALGO VARCHAR(255), + KEY_ENCRYPTION_ALGO VARCHAR(255), + ATTR_PROFILE_ENABLED BOOLEAN NOT NULL, + ATTR_SERVICE_INDEX VARCHAR(255), + SLO_PROFILE_ENABLED BOOLEAN NOT NULL, + SLO_METHOD VARCHAR(255), + SLO_RESPONSE_URL VARCHAR(2048), + SLO_REQUEST_URL VARCHAR(2048), + IDP_INIT_SSO_ENABLED BOOLEAN, + IDP_INIT_SLO_ENABLED BOOLEAN, + QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL, + ECP_ENABLED BOOLEAN NOT NULL, + ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN, + IDP_ENTITY_ID_ALIAS VARCHAR(255), + ISSUER_QUALIFIER VARCHAR(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT DATETIME NOT NULL, + UPDATED_AT DATETIME NOT NULL, + PRIMARY KEY (ID) +) ENGINE NDB; + +CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + PROPERTY_NAME VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER(ID) ON DELETE CASCADE +) ENGINE NDB; + CREATE TABLE IDN_ORG_USER_INVITATION ( ID INTEGER NOT NULL AUTO_INCREMENT, INVITATION_ID VARCHAR(40) NOT NULL, @@ -1718,3 +1763,8 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); -- RULES -- CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + +-- SAML -- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql index 6a1eb37a6492..b2839a229674 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/mysql.sql @@ -1247,6 +1247,51 @@ CREATE TABLE IF NOT EXISTS IDN_OAUTH_PAR ( PARAMETERS MEDIUMTEXT )DEFAULT CHARACTER SET latin1 ENGINE INNODB; +CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL AUTO_INCREMENT, + ISSUER VARCHAR(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR(255) NOT NULL, + CERT_ALIAS VARCHAR(255), + REQ_SIG_VALIDATION BOOLEAN, + SIGN_RESPONSE BOOLEAN NOT NULL, + SIGN_ASSERTIONS BOOLEAN NOT NULL, + SIGNING_ALGO VARCHAR(255) NOT NULL, + DIGEST_ALGO VARCHAR(255) NOT NULL, + ENCRYPT_ASSERTION BOOLEAN, + ASSERTION_ENCRYPTION_ALGO VARCHAR(255), + KEY_ENCRYPTION_ALGO VARCHAR(255), + ATTR_PROFILE_ENABLED BOOLEAN NOT NULL, + ATTR_SERVICE_INDEX VARCHAR(255), + SLO_PROFILE_ENABLED BOOLEAN NOT NULL, + SLO_METHOD VARCHAR(255), + SLO_RESPONSE_URL VARCHAR(2048), + SLO_REQUEST_URL VARCHAR(2048), + IDP_INIT_SSO_ENABLED BOOLEAN, + IDP_INIT_SLO_ENABLED BOOLEAN, + QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL, + ECP_ENABLED BOOLEAN NOT NULL, + ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN, + IDP_ENTITY_ID_ALIAS VARCHAR(255), + ISSUER_QUALIFIER VARCHAR(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, + PRIMARY KEY (ID) +) DEFAULT CHARACTER SET latin1 ENGINE INNODB; + +CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL AUTO_INCREMENT, + PROPERTY_NAME VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE +) DEFAULT CHARACTER SET latin1 ENGINE INNODB; + CREATE TABLE IDN_ORG_USER_INVITATION ( ID INTEGER NOT NULL AUTO_INCREMENT, INVITATION_ID VARCHAR(40) NOT NULL, @@ -1554,3 +1599,8 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); -- RULES -- CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + +-- SAML -- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql index 9e127808dceb..019f97e114fa 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle.sql @@ -2016,6 +2016,73 @@ CREATE TABLE IDN_OAUTH_PAR ( PARAMETERS CLOB ) / +CREATE TABLE IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL, + ISSUER VARCHAR2(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR2(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR2(255) NOT NULL, + CERT_ALIAS VARCHAR2(255), + REQ_SIG_VALIDATION CHAR(1), + SIGN_RESPONSE CHAR(1) NOT NULL, + SIGN_ASSERTIONS CHAR(1) NOT NULL, + SIGNING_ALGO VARCHAR2(255) NOT NULL, + DIGEST_ALGO VARCHAR2(255) NOT NULL, + ENCRYPT_ASSERTION CHAR(1), + ASSERTION_ENCRYPTION_ALGO VARCHAR2(255), + KEY_ENCRYPTION_ALGO VARCHAR2(255), + ATTR_PROFILE_ENABLED CHAR(1) NOT NULL, + ATTR_SERVICE_INDEX VARCHAR2(255), + SLO_PROFILE_ENABLED CHAR(1) NOT NULL, + SLO_METHOD VARCHAR2(255), + SLO_RESPONSE_URL VARCHAR2(2048), + SLO_REQUEST_URL VARCHAR2(2048), + IDP_INIT_SSO_ENABLED CHAR(1), + IDP_INIT_SLO_ENABLED CHAR(1), + QUERY_REQUEST_PROFILE_ENABLED CHAR(1) NOT NULL, + ECP_ENABLED CHAR(1) NOT NULL, + ARTIFACT_BINDING_ENABLED CHAR(1) NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION CHAR(1), + IDP_ENTITY_ID_ALIAS VARCHAR2(255), + ISSUER_QUALIFIER VARCHAR2(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR2(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, + PRIMARY KEY (ID) +) +/ +CREATE SEQUENCE IDN_SAML2_SERVICE_PROVIDER_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_SAML2_SERVICE_PROVIDER_TRIG + BEFORE INSERT + ON IDN_SAML2_SERVICE_PROVIDER + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDN_SAML2_SERVICE_PROVIDER_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL, + PROPERTY_NAME VARCHAR2(255) NOT NULL, + PROPERTY_VALUE VARCHAR2(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER(ID) ON DELETE CASCADE +) +/ +CREATE SEQUENCE IDN_SAML2_SP_PROPERTIES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_SAML2_SP_PROPERTIES_TRIG + BEFORE INSERT + ON IDN_SAML2_SP_PROPERTIES + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDN_SAML2_SP_PROPERTIES_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ CREATE TABLE IDN_ORG_USER_INVITATION ( ID INTEGER NOT NULL, INVITATION_ID VARCHAR(40) NOT NULL, @@ -2386,3 +2453,11 @@ CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID) / CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID) / + +-- SAML -- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +/ +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +/ +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); +/ diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql index 9b90807829d4..bfc0770cee94 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/oracle_rac.sql @@ -1849,6 +1849,73 @@ CREATE TABLE IDN_OAUTH_PAR ( PARAMETERS CLOB ) / +CREATE TABLE IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL, + ISSUER VARCHAR(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR(255) NOT NULL, + CERT_ALIAS VARCHAR(255), + REQ_SIG_VALIDATION CHAR(1), + SIGN_RESPONSE CHAR(1) NOT NULL, + SIGN_ASSERTIONS CHAR(1) NOT NULL, + SIGNING_ALGO VARCHAR(255) NOT NULL, + DIGEST_ALGO VARCHAR(255) NOT NULL, + ENCRYPT_ASSERTION CHAR(1), + ASSERTION_ENCRYPTION_ALGO VARCHAR(255), + KEY_ENCRYPTION_ALGO VARCHAR(255), + ATTR_PROFILE_ENABLED CHAR(1) NOT NULL, + ATTR_SERVICE_INDEX VARCHAR(255), + SLO_PROFILE_ENABLED CHAR(1) NOT NULL, + SLO_METHOD VARCHAR(255), + SLO_RESPONSE_URL VARCHAR(2048), + SLO_REQUEST_URL VARCHAR(2048), + IDP_INIT_SSO_ENABLED CHAR(1), + IDP_INIT_SLO_ENABLED CHAR(1), + QUERY_REQUEST_PROFILE_ENABLED CHAR(1) NOT NULL, + ECP_ENABLED CHAR(1) NOT NULL, + ARTIFACT_BINDING_ENABLED CHAR(1) NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION CHAR(1), + IDP_ENTITY_ID_ALIAS VARCHAR(255), + ISSUER_QUALIFIER VARCHAR(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, + PRIMARY KEY (ID) +) +/ +CREATE SEQUENCE IDN_SAML2_SERVICE_PROVIDER_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_SAML2_SERVICE_PROVIDER_TRIG + BEFORE INSERT + ON IDN_SAML2_SERVICE_PROVIDER + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDN_SAML2_SERVICE_PROVIDER_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ +CREATE TABLE IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL, + PROPERTY_NAME VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER(ID) ON DELETE CASCADE +) +/ +CREATE SEQUENCE IDN_SAML2_SP_PROPERTIES_SEQ START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER IDN_SAML2_SP_PROPERTIES_TRIG + BEFORE INSERT + ON IDN_SAML2_SP_PROPERTIES + REFERENCING NEW AS NEW + FOR EACH ROW + BEGIN + SELECT IDN_SAML2_SP_PROPERTIES_SEQ.nextval INTO :NEW.ID FROM dual; + END; +/ CREATE TABLE IDN_ORG_USER_INVITATION ( ID INTEGER NOT NULL, INVITATION_ID VARCHAR(40) NOT NULL, @@ -2290,3 +2357,11 @@ CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID) / CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID) / + +-- SAML -- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +/ +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +/ +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); +/ diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql index 185115350c3b..7b51ab2cf7c6 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/dbscripts/postgresql.sql @@ -1455,6 +1455,57 @@ CREATE TABLE IDN_OAUTH_PAR ( PARAMETERS TEXT ); +DROP TABLE IF EXISTS IDN_SAML2_SERVICE_PROVIDER; +DROP SEQUENCE IF EXISTS IDN_SAML2_SP_SEQ; +CREATE SEQUENCE IDN_SAML2_SP_SEQ; +CREATE TABLE IF NOT EXISTS IDN_SAML2_SERVICE_PROVIDER ( + ID INTEGER NOT NULL DEFAULT NEXTVAL('IDN_SAML2_SERVICE_PROVIDER_SEQ'), + ISSUER VARCHAR(255) NOT NULL, + DEFAULT_ASSERTION_CONSUMER_URL VARCHAR(2048) NOT NULL, + NAME_ID_FORMAT VARCHAR(255) NOT NULL, + CERT_ALIAS VARCHAR(255), + REQ_SIG_VALIDATION BOOLEAN, + SIGN_RESPONSE BOOLEAN NOT NULL, + SIGN_ASSERTIONS BOOLEAN NOT NULL, + SIGNING_ALGO VARCHAR(255) NOT NULL, + DIGEST_ALGO VARCHAR(255) NOT NULL, + ENCRYPT_ASSERTION BOOLEAN, + ASSERTION_ENCRYPTION_ALGO VARCHAR(255), + KEY_ENCRYPTION_ALGO VARCHAR(255), + ATTR_PROFILE_ENABLED BOOLEAN NOT NULL, + ATTR_SERVICE_INDEX VARCHAR(255), + SLO_PROFILE_ENABLED BOOLEAN NOT NULL, + SLO_METHOD VARCHAR(255), + SLO_RESPONSE_URL VARCHAR(2048), + SLO_REQUEST_URL VARCHAR(2048), + IDP_INIT_SSO_ENABLED BOOLEAN, + IDP_INIT_SLO_ENABLED BOOLEAN, + QUERY_REQUEST_PROFILE_ENABLED BOOLEAN NOT NULL, + ECP_ENABLED BOOLEAN NOT NULL, + ARTIFACT_BINDING_ENABLED BOOLEAN NOT NULL, + ARTIFACT_RESOLVE_REQ_SIG_VALIDATION BOOLEAN, + IDP_ENTITY_ID_ALIAS VARCHAR(255), + ISSUER_QUALIFIER VARCHAR(255), + SUPPORTED_ASSERTION_QUERY_REQUEST_TYPES VARCHAR(255), + TENANT_ID INTEGER, + VERSION VARCHAR(15) NOT NULL, + CREATED_AT TIMESTAMP NOT NULL, + UPDATED_AT TIMESTAMP NOT NULL, + PRIMARY KEY (ID) +); + +DROP TABLE IF EXISTS IDN_SAML2_SP_PROPERTIES; +DROP SEQUENCE IF EXISTS IDN_SAML2_SP_PROPERTY_SEQ; +CREATE SEQUENCE IDN_SAML2_SP_PROPERTY_SEQ; +CREATE TABLE IF NOT EXISTS IDN_SAML2_SP_PROPERTIES ( + ID INTEGER NOT NULL DEFAULT NEXTVAL('IDN_SAML2_SP_PROPERTIES_SEQ'), + PROPERTY_NAME VARCHAR(255) NOT NULL, + PROPERTY_VALUE VARCHAR(2048) NOT NULL, + SP_ID INTEGER NOT NULL, + PRIMARY KEY (ID), + FOREIGN KEY (SP_ID) REFERENCES IDN_SAML2_SERVICE_PROVIDER (ID) ON DELETE CASCADE +); + DROP TABLE IF EXISTS IDN_ORG_USER_INVITATION; DROP SEQUENCE IF EXISTS IDN_ORG_USER_INVITATION_SEQ; CREATE SEQUENCE IDN_ORG_USER_INVITATION_SEQ; @@ -1807,3 +1858,8 @@ CREATE INDEX IDX_IDN_CERTIFICATE_UUID_TID ON IDN_CERTIFICATE (UUID, TENANT_ID); -- RULES -- CREATE INDEX IDX_IDN_RULE_UUID_TID ON IDN_RULE (UUID, TENANT_ID); CREATE INDEX IDX_IDN_RULE_REF_RID_TID ON IDN_RULE_REFERENCES (RULE_ID, TENANT_ID); + +-- SAML -- +CREATE INDEX IDX_SAML2_SP_ISSUER ON IDN_SAML2_SERVICE_PROVIDER (ISSUER, TENANT_ID); +CREATE INDEX IDX_SAML2_SP_TENANT_ID ON IDN_SAML2_SERVICE_PROVIDER (TENANT_ID); +CREATE INDEX IDX_SAML2_SP_PROPERTIES ON IDN_SAML2_SP_PROPERTIES (SP_ID); diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml index 4578a389f1b3..5e5159bfa1c3 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml @@ -77,7 +77,7 @@ --> database - + database diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 index 9e5fe3ded889..e586c1a6c036 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/identity.xml.j2 @@ -87,6 +87,7 @@ {{data_storage_type.notification_templates}} {{data_storage_type.xacml}} + {{data_storage_type.saml}} diff --git a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json index 199e02614d84..03bd28992be9 100644 --- a/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json +++ b/features/identity-core/org.wso2.carbon.identity.core.server.feature/resources/org.wso2.carbon.identity.core.server.feature.default.json @@ -11,6 +11,7 @@ "identity_data_source.skip_db_schema_creation": false, "identity_data_source.skip_claim_metadata_persistence": true, "data_storage_type.notification_templates": "database", + "data_storage_type.saml": "database", "database.identity_db.pool_options.maxActive": "50", "database.identity_db.pool_options.maxWait": "60000", "database.identity_db.pool_options.testOnBorrow": "true",