RED-5504 - Prevent using exact same database schema/buckets/index for multiple tenants
- add unique constraints to tenants table
This commit is contained in:
parent
ab6b0a5313
commit
0decb33035
@ -12,6 +12,7 @@ import java.sql.DriverManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
@ -86,6 +87,7 @@ public class TenantManagementService {
|
||||
private final GeneralConfigurationService generalConfigurationService;
|
||||
private final KeyCloakRoleManagerService keyCloakRoleManagerService;
|
||||
private final KeyCloakAdminClientService keycloak;
|
||||
private final Map<String, String> tenantsHostAndSchemaMap = new HashMap<>();
|
||||
|
||||
|
||||
public TenantManagementService(EncryptionDecryptionService encryptionService,
|
||||
@ -201,8 +203,16 @@ public class TenantManagementService {
|
||||
}
|
||||
|
||||
|
||||
private void checkDuplicateHostAndSchema(String hostAndSchemaName) {
|
||||
|
||||
if (tenantsHostAndSchemaMap.containsValue(hostAndSchemaName)) {
|
||||
throw ConflictException.withObjectName("host and schema");
|
||||
}
|
||||
}
|
||||
|
||||
private void createSchema(TenantRequest tenantRequest) {
|
||||
|
||||
checkDuplicateHostAndSchema(buildHostAndSchemaName(tenantRequest.getDatabaseConnection()));
|
||||
var jdbcUrl = JDBCUtils.buildJdbcUrl(tenantRequest.getDatabaseConnection());
|
||||
try (Connection connection = DriverManager.getConnection(jdbcUrl,
|
||||
tenantRequest.getDatabaseConnection().getUsername(),
|
||||
@ -212,11 +222,20 @@ public class TenantManagementService {
|
||||
jdbcTemplate.execute((StatementCallback<Boolean>) stmt -> stmt.execute("CREATE SCHEMA " + tenantRequest.getDatabaseConnection().getSchema()));
|
||||
jdbcTemplate.execute((StatementCallback<Boolean>) stmt -> stmt.execute("GRANT USAGE ON SCHEMA " + tenantRequest.getDatabaseConnection()
|
||||
.getSchema() + " TO " + tenantRequest.getDatabaseConnection().getUsername()));
|
||||
|
||||
tenantsHostAndSchemaMap.put(tenantRequest.getTenantId(), buildHostAndSchemaName(tenantRequest.getDatabaseConnection()));
|
||||
} catch (Exception e) {
|
||||
log.info("Could not create schema, ignoring");
|
||||
}
|
||||
}
|
||||
|
||||
private String buildHostAndSchemaName(DatabaseConnection databaseConnection) {
|
||||
StringBuilder sb = new StringBuilder(databaseConnection.getHost())
|
||||
.append("currentSchema=")
|
||||
.append(databaseConnection.getSchema());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
private boolean tryToAccessRealm(String tenantId) {
|
||||
|
||||
|
||||
@ -5,3 +5,5 @@ databaseChangeLog:
|
||||
file: db/changelog/master/2-quartz.changelog.yaml
|
||||
- include:
|
||||
file: db/changelog/master/3-detailed-db-connection.changelog.yaml
|
||||
- include:
|
||||
file: db/changelog/master/4-add-unique-constraint-for-tenants-table.yaml
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
databaseChangeLog:
|
||||
- changeSet:
|
||||
id: add-unique-constraint-for-tenants-table
|
||||
author: corinaolariu
|
||||
changes:
|
||||
- addUniqueConstraint:
|
||||
columnNames: db_host, db_schema
|
||||
constraintName: unique_constraint_tenant_host_shema
|
||||
tableName: tenant
|
||||
- addUniqueConstraint:
|
||||
columnNames: storage_s3_endpoint, storage_s3_region, storage_s3_bucket_name
|
||||
constraintName: unique_constraint_tenant_s3_storage
|
||||
tableName: tenant
|
||||
- addUniqueConstraint:
|
||||
columnNames: storage_azure_connection_string, storage_azure_container_name
|
||||
constraintName: unique_constraint_tenant_azure_storage
|
||||
tableName: tenant
|
||||
@ -0,0 +1,71 @@
|
||||
package com.iqser.red.service.peristence.v1.server.integration.tests;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.iqser.red.keycloak.commons.roles.ApplicationRoles;
|
||||
import com.iqser.red.service.peristence.v1.server.integration.client.TenantsClient;
|
||||
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.multitenancy.DatabaseConnection;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.multitenancy.RedUser;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.multitenancy.S3StorageConnection;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.multitenancy.SearchConnection;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.multitenancy.TenantRequest;
|
||||
|
||||
import feign.FeignException;
|
||||
|
||||
public class TenantsTest extends AbstractPersistenceServerServiceTest {
|
||||
|
||||
@Autowired
|
||||
private TenantsClient tenantsClient;
|
||||
|
||||
@Test
|
||||
public void testCreateTenantWithSameHostAndSchema() {
|
||||
|
||||
var tenantRequest = TenantRequest.builder()
|
||||
.tenantId("redaction2")
|
||||
.displayName("Redaction default2")
|
||||
.guid(UUID.randomUUID().toString())
|
||||
.databaseConnection(DatabaseConnection.builder()
|
||||
.driver("postgresql")
|
||||
.host("localhost")
|
||||
.port("port")
|
||||
.database("redaction")
|
||||
.schema("myschema")
|
||||
.username("redaction")
|
||||
.password("redaction")
|
||||
.build())
|
||||
.searchConnection(SearchConnection.builder()
|
||||
.hosts(Set.of("elasticsearchHost2"))
|
||||
.port(9200)
|
||||
.scheme("https2")
|
||||
.username("elastic")
|
||||
.numberOfShards("1")
|
||||
.numberOfReplicas("5")
|
||||
.build())
|
||||
.s3StorageConnection(S3StorageConnection.builder()
|
||||
.key("key")
|
||||
.secret("secret")
|
||||
.signerType("signerType")
|
||||
.bucketName("bucketName2")
|
||||
.region("eu")
|
||||
.endpoint("endpoint2")
|
||||
.build())
|
||||
.redUsers(List.of(RedUser.builder().username("user").password("password").redRoles(ApplicationRoles.ROLE_DATA.keySet()).build(),
|
||||
RedUser.builder().username("manageradmin1@test.com").password("secret").redRoles(ApplicationRoles.ROLE_DATA.keySet()).build(),
|
||||
RedUser.builder().username("manageradmin2@test.com").password("secret").redRoles(ApplicationRoles.ROLE_DATA.keySet()).build()))
|
||||
.build();
|
||||
|
||||
try {
|
||||
tenantsClient.createTenant(tenantRequest);
|
||||
} catch(FeignException e) {
|
||||
assertThat(e.status()).isEqualTo(409);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user