RED-8123 - privilege escalation is not checked/validated
This commit is contained in:
parent
7462b38f9f
commit
8a41d70701
@ -1,9 +1,15 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Object containing the request to reset a password.")
|
||||
public class ResetPasswordRequest {
|
||||
|
||||
|
||||
@ -14,16 +14,6 @@ import javax.ws.rs.NotAuthorizedException;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.apache.commons.validator.routines.EmailValidator;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
@ -46,10 +36,19 @@ import com.knecon.fforesight.tenantusermanagement.model.UpdateMyProfileRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateProfileRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.User;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.validator.routines.EmailValidator;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -127,16 +126,6 @@ public class UserService {
|
||||
}
|
||||
|
||||
|
||||
private void sendResetPasswordEmail(String userId) {
|
||||
|
||||
try {
|
||||
this.getTenantUsersResource().get(userId).executeActionsEmail(Collections.singletonList("UPDATE_PASSWORD"), 86400);
|
||||
} catch (Exception e) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to send email.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@CacheEvict(value = "${commons.keycloak.userCache}", allEntries = true, beforeInvocation = true)
|
||||
public User setRoles(String userId, Set<String> newRoles, Set<String> currentUserRoles) {
|
||||
|
||||
@ -200,31 +189,12 @@ public class UserService {
|
||||
}
|
||||
|
||||
|
||||
private RoleRepresentation getRoleRepresentation(String role) {
|
||||
|
||||
RoleRepresentation realmRole;
|
||||
try {
|
||||
realmRole = realmService.realm(TenantContext.getTenantId()).roles().get(role).toRepresentation();
|
||||
} catch (NotFoundException e) {
|
||||
log.warn("The realm role {} is not found.", role);
|
||||
throw new NotFoundException("The realm role " + role + " is not found.", e);
|
||||
}
|
||||
return realmRole;
|
||||
}
|
||||
|
||||
|
||||
public Optional<User> getUserById(String userId) {
|
||||
|
||||
return userListingService.getAllUsers(TenantContext.getTenantId()).stream().filter(u -> u.getUserId().equalsIgnoreCase(userId)).findAny();
|
||||
}
|
||||
|
||||
|
||||
public List<User> getUsersByIds(Collection<String> userIds) {
|
||||
|
||||
return userListingService.getAllUsers(TenantContext.getTenantId()).stream().filter(u -> userIds.contains(u.getUserId())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@CacheEvict(value = "${commons.keycloak.userCache}", allEntries = true, beforeInvocation = true)
|
||||
public User updateMyProfile(UpdateMyProfileRequest updateProfileRequest) {
|
||||
|
||||
@ -366,20 +336,14 @@ public class UserService {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "Cannot delete self");
|
||||
}
|
||||
|
||||
var currentUserResource = getUserResource(KeycloakSecurity.getUserId());
|
||||
var currentRoles = getRoles(currentUserResource.toRepresentation().getId());
|
||||
var executionValid = isExecutionRankValid(KeycloakSecurity.getUserId(), userId);
|
||||
|
||||
var userResource = getUserResource(userId);
|
||||
var userRoles = getRoles(userId);
|
||||
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var maxRank = currentRoles.stream().map(r -> roleMapping.getRole(r).getRank()).max(Integer::compare).orElse(-1);
|
||||
var toDeleteUserMaxRank = userRoles.stream().map(r -> roleMapping.getRole(r).getRank()).max(Integer::compare).orElse(-1);
|
||||
|
||||
if (toDeleteUserMaxRank > maxRank) {
|
||||
if (!executionValid) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to delete a user with higher ranking roles");
|
||||
}
|
||||
|
||||
var userResource = getUserResource(userId);
|
||||
|
||||
var userToBeRemoved = getUserByUsername(userResource.toRepresentation().getUsername());
|
||||
userResource.remove();
|
||||
|
||||
@ -443,12 +407,19 @@ public class UserService {
|
||||
|
||||
public void resetPassword(String userId, ResetPasswordRequest resetPasswordRequest) {
|
||||
|
||||
var executionValid = isExecutionRankValid(KeycloakSecurity.getUserId(), userId);
|
||||
|
||||
if (!executionValid) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to reset the password of a user with higher ranking roles");
|
||||
}
|
||||
|
||||
try {
|
||||
CredentialRepresentation request = new CredentialRepresentation();
|
||||
request.setType(CredentialRepresentation.PASSWORD);
|
||||
request.setTemporary(resetPasswordRequest.isTemporary());
|
||||
request.setValue(resetPasswordRequest.getPassword());
|
||||
realmService.realm(TenantContext.getTenantId()).users().get(userId).resetPassword(request);
|
||||
log.info("User {} resetted password for user {}", KeycloakSecurity.getUserId(), userId);
|
||||
} catch (Exception e) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Could not reset password. It does not match the password policy.", e);
|
||||
}
|
||||
@ -460,4 +431,43 @@ public class UserService {
|
||||
return userListingService.getAllUsers(TenantContext.getTenantId());
|
||||
}
|
||||
|
||||
|
||||
private RoleRepresentation getRoleRepresentation(String role) {
|
||||
|
||||
RoleRepresentation realmRole;
|
||||
try {
|
||||
realmRole = realmService.realm(TenantContext.getTenantId()).roles().get(role).toRepresentation();
|
||||
} catch (NotFoundException e) {
|
||||
log.warn("The realm role {} is not found.", role);
|
||||
throw new NotFoundException("The realm role " + role + " is not found.", e);
|
||||
}
|
||||
return realmRole;
|
||||
}
|
||||
|
||||
|
||||
private void sendResetPasswordEmail(String userId) {
|
||||
|
||||
try {
|
||||
this.getTenantUsersResource().get(userId).executeActionsEmail(Collections.singletonList("UPDATE_PASSWORD"), 86400);
|
||||
} catch (Exception e) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Failed to send email.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isExecutionRankValid(String executingUserId, String targetUserId) {
|
||||
|
||||
var currentUserResource = getUserResource(executingUserId);
|
||||
var currentRoles = getRoles(currentUserResource.toRepresentation().getId());
|
||||
|
||||
var userRoles = getRoles(targetUserId);
|
||||
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var maxRank = currentRoles.stream().map(r -> roleMapping.getRole(r).getRank()).max(Integer::compare).orElse(-1);
|
||||
var targetRank = userRoles.stream().map(r -> roleMapping.getRole(r).getRank()).max(Integer::compare).orElse(-1);
|
||||
|
||||
return targetRank <= maxRank;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
package com.knecon.fforesight;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
@ -17,7 +15,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import com.knecon.fforesight.feigntestclients.external.TenantsClient;
|
||||
import com.knecon.fforesight.feigntestclients.internal.InternalTenantsClient;
|
||||
@ -27,9 +24,11 @@ import com.knecon.fforesight.testcontainers.MinioTestContainer;
|
||||
import com.knecon.fforesight.testcontainers.RedisTestContainer;
|
||||
import com.knecon.fforesight.testcontainers.SpringPostgreSQLTestContainer;
|
||||
import com.knecon.fforesight.utils.TestTenantService;
|
||||
|
||||
import com.knecon.fforesight.utils.TokenService;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@EnableFeignClients(basePackageClasses = {TenantsClient.class, InternalTenantsClient.class})
|
||||
@ -38,17 +37,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@SpringBootTest(classes = TenantUserManagementServiceApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||
public class AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
public final static String TEST_TENANT_ID = "test-tenant-fforesight";
|
||||
public static int minioPort;
|
||||
@MockBean
|
||||
protected RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Autowired
|
||||
protected TestTenantService testTenantService;
|
||||
|
||||
public final static String TEST_TENANT_ID = "test-tenant-fforesight";
|
||||
|
||||
private static GenericContainer minioServer;
|
||||
|
||||
public static int minioPort;
|
||||
@Autowired
|
||||
protected TokenService tokenService;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
|
||||
@ -4,7 +4,7 @@ import org.springframework.cloud.openfeign.FeignClient;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.api.external.GeneralSettingsResource;
|
||||
|
||||
@FeignClient(name = "GeneralSettingsClient", url = "http://localhost:${server.port}" ,path = "${fforesight.tenant-user-management.base-path:}")
|
||||
@FeignClient(name = "GeneralSettingsClient", url = "http://localhost:${server.port}", path = "${fforesight.tenant-user-management.base-path:}")
|
||||
public interface GeneralSettingsClient extends GeneralSettingsResource {
|
||||
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import org.springframework.cloud.openfeign.FeignClient;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.api.external.SMTPConfigurationResource;
|
||||
|
||||
@FeignClient(name = "SMTPConfigurationClient", url = "http://localhost:${server.port}",path = "${fforesight.tenant-user-management.base-path:}")
|
||||
@FeignClient(name = "SMTPConfigurationClient", url = "http://localhost:${server.port}", path = "${fforesight.tenant-user-management.base-path:}")
|
||||
public interface SMTPConfigurationClient extends SMTPConfigurationResource {
|
||||
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import org.springframework.cloud.openfeign.FeignClient;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.api.external.TenantsResource;
|
||||
|
||||
@FeignClient(name = "TenantsClient", url = "http://localhost:${server.port}",path = "${fforesight.tenant-user-management.base-path:}")
|
||||
@FeignClient(name = "TenantsClient", url = "http://localhost:${server.port}", path = "${fforesight.tenant-user-management.base-path:}")
|
||||
public interface TenantsClient extends TenantsResource {
|
||||
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import org.springframework.cloud.openfeign.FeignClient;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.api.external.UserResource;
|
||||
|
||||
@FeignClient(name = "UserClient", url = "http://localhost:${server.port}",path = "${fforesight.tenant-user-management.base-path:}")
|
||||
@FeignClient(name = "UserClient", url = "http://localhost:${server.port}", path = "${fforesight.tenant-user-management.base-path:}")
|
||||
public interface UserClient extends UserResource {
|
||||
|
||||
}
|
||||
|
||||
@ -3,13 +3,12 @@ package com.knecon.fforesight.testcontainers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dasniko.testcontainers.keycloak.KeycloakContainer;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
|
||||
import dasniko.testcontainers.keycloak.KeycloakContainer;
|
||||
|
||||
public final class KeyCloakTestContainer {
|
||||
|
||||
private static final String IMAGE_VERSION = "quay.io/keycloak/keycloak:21.0.0";
|
||||
|
||||
@ -8,6 +8,7 @@ public final class MinioTestContainer extends GenericContainer<MinioTestContaine
|
||||
private static final String IMAGE_VERSION = "minio/minio";
|
||||
private static MinioTestContainer container;
|
||||
|
||||
|
||||
private MinioTestContainer() {
|
||||
|
||||
super(DockerImageName.parse(IMAGE_VERSION));
|
||||
@ -24,4 +25,5 @@ public final class MinioTestContainer extends GenericContainer<MinioTestContaine
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,21 +2,13 @@ package com.knecon.fforesight.tests;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.testcontainers.Testcontainers;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.startupcheck.OneShotStartupCheckStrategy;
|
||||
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
|
||||
import com.knecon.fforesight.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.feigntestclients.external.GeneralSettingsClient;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.GeneralConfigurationModel;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class GeneralSettingsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
|
||||
@ -6,9 +6,9 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
public class IdentityTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
public void test() {
|
||||
|
||||
assumeTrue(true);
|
||||
}
|
||||
|
||||
|
||||
@ -3,18 +3,19 @@ package com.knecon.fforesight.tests;
|
||||
import static dasniko.testcontainers.keycloak.ExtendableKeycloakContainer.MASTER_REALM;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.knecon.fforesight.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.RealmService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
||||
public class RealmTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private RealmService realmService;
|
||||
|
||||
|
||||
@Test
|
||||
public void testInitialRealm() {
|
||||
|
||||
@ -22,4 +23,5 @@ public class RealmTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
assertEquals(realmRepresentation.getDisplayName(), "tenant-user-management");
|
||||
assertEquals(realmRepresentation.getLoginTheme(), "redaction");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3,13 +3,13 @@ package com.knecon.fforesight.tests;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.knecon.fforesight.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.feigntestclients.external.SMTPConfigurationClient;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SMTPConfiguration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class SMTPConfigurationTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
@ -43,17 +43,6 @@ public class SMTPConfigurationTest extends AbstractTenantUserManagementIntegrati
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSMTPConnection() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
|
||||
SMTPConfiguration smtpConfiguration = provideTestSMTPConfiguration();
|
||||
|
||||
assertThatThrownBy(() -> smtpConfigurationClient.testSMTPConfiguration(smtpConfiguration)).hasMessageContaining("Couldn't connect to host, port: test.knecon.com, 25; timeout 10000");
|
||||
|
||||
TenantContext.clear();
|
||||
}
|
||||
|
||||
private SMTPConfiguration provideTestSMTPConfiguration() {
|
||||
|
||||
@ -70,4 +59,17 @@ public class SMTPConfigurationTest extends AbstractTenantUserManagementIntegrati
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSMTPConnection() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
|
||||
SMTPConfiguration smtpConfiguration = provideTestSMTPConfiguration();
|
||||
|
||||
assertThatThrownBy(() -> smtpConfigurationClient.testSMTPConfiguration(smtpConfiguration)).hasMessageContaining(
|
||||
"Couldn't connect to host, port: test.knecon.com, 25; timeout 10000");
|
||||
|
||||
TenantContext.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,11 +2,11 @@ package com.knecon.fforesight.tests;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.knecon.fforesight.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.feigntestclients.internal.InternalTenantsClient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class StartupTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
|
||||
@ -6,12 +6,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.knecon.fforesight.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.feigntestclients.external.TenantsClient;
|
||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantcommons.model.AzureStorageConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.DatabaseConnection;
|
||||
@ -19,29 +17,22 @@ import com.knecon.fforesight.tenantcommons.model.S3StorageConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.SearchConnection;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SearchConnectionRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.RealmService;
|
||||
import com.knecon.fforesight.utils.TestTenantService;
|
||||
|
||||
import feign.FeignException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
||||
public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
private static final String PASSWORD = "**********";
|
||||
@Autowired
|
||||
private TenantsClient tenantsClient;
|
||||
|
||||
@Autowired
|
||||
private TestTenantService testTenantService;
|
||||
|
||||
@Autowired
|
||||
private EncryptionDecryptionService encryptionService;
|
||||
|
||||
@Autowired
|
||||
private RealmService realmService;
|
||||
|
||||
private static final String PASSWORD = "**********";
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateNewTenant() {
|
||||
@ -68,6 +59,7 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void testUpdateTenant() {
|
||||
|
||||
String tenantId = "new_tenant";
|
||||
testTenantService.createTestTenantIfNotExists(tenantId, minioPort);
|
||||
TenantContext.setTenantId(tenantId);
|
||||
@ -131,6 +123,21 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
}
|
||||
|
||||
|
||||
private SearchConnection convert(SearchConnectionRequest sc, String tenantId) {
|
||||
|
||||
return SearchConnection.builder()
|
||||
.hosts(sc.getHosts())
|
||||
.port(sc.getPort())
|
||||
.scheme(sc.getScheme())
|
||||
.username(sc.getUsername())
|
||||
.password(sc.getPassword())
|
||||
.numberOfShards(sc.getNumberOfShards())
|
||||
.numberOfReplicas(sc.getNumberOfReplicas())
|
||||
.indexPrefix("fforesight_" + tenantId)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpdateTenantWithIncorrectS3Storage() {
|
||||
|
||||
@ -253,17 +260,4 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
TenantContext.clear();
|
||||
}
|
||||
|
||||
|
||||
private SearchConnection convert(SearchConnectionRequest sc, String tenantId) {
|
||||
return SearchConnection.builder()
|
||||
.hosts(sc.getHosts())
|
||||
.port(sc.getPort())
|
||||
.scheme(sc.getScheme())
|
||||
.username(sc.getUsername())
|
||||
.password(sc.getPassword())
|
||||
.numberOfShards(sc.getNumberOfShards())
|
||||
.numberOfReplicas(sc.getNumberOfReplicas())
|
||||
.indexPrefix("fforesight_" + tenantId)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,29 +4,30 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.knecon.fforesight.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.feigntestclients.external.UserPreferenceClient;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class UserPreferenceTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private UserPreferenceClient userPreferenceClient;
|
||||
|
||||
|
||||
@Test
|
||||
public void testUserPreferences(){
|
||||
public void testUserPreferences() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
|
||||
var allMyAttributes = userPreferenceClient.getAllUserAttributes();
|
||||
assertThat(allMyAttributes).isEmpty();
|
||||
|
||||
userPreferenceClient.setAttribute("test", List.of("1","2","3"));
|
||||
userPreferenceClient.setAttribute("test", List.of("1", "2", "3"));
|
||||
allMyAttributes = userPreferenceClient.getAllUserAttributes();
|
||||
assertThat(allMyAttributes).hasEntrySatisfying("test", k -> assertThat(k).containsExactly("1","2","3"));
|
||||
assertThat(allMyAttributes).hasEntrySatisfying("test", k -> assertThat(k).containsExactly("1", "2", "3"));
|
||||
|
||||
userPreferenceClient.deleteAttribute("test");
|
||||
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
package com.knecon.fforesight.tests;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.knecon.fforesight.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.feigntestclients.external.UserClient;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateUserRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.ResetPasswordRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateMyProfileRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateProfileRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
import feign.FeignException;
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
@ -44,7 +49,8 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
var testUser = userClient.getUserById(testUserId);
|
||||
assertThat(testUser).isNotNull();
|
||||
|
||||
testUser = userClient.updateMyProfile(UpdateMyProfileRequest.builder().email("test@fforesight.com").firstName("updateTestFirstName").lastName("updateTestLastName").build());
|
||||
testUser =
|
||||
userClient.updateMyProfile(UpdateMyProfileRequest.builder().email("test@fforesight.com").firstName("updateTestFirstName").lastName("updateTestLastName").build());
|
||||
assertThat(testUser.getLastName()).isEqualTo("updateTestLastName");
|
||||
assertThat(testUser.getFirstName()).isEqualTo("updateTestFirstName");
|
||||
|
||||
@ -69,7 +75,12 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
assertThat(createdUser.getRoles()).isEmpty();
|
||||
|
||||
createdUser = userClient.updateProfile(createdUser.getUserId(),
|
||||
UpdateProfileRequest.builder().email("test.new.user@knecon.com").firstName("update test").lastName("update test").roles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles()).build());
|
||||
UpdateProfileRequest.builder()
|
||||
.email("test.new.user@knecon.com")
|
||||
.firstName("update test")
|
||||
.lastName("update test")
|
||||
.roles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles())
|
||||
.build());
|
||||
assertThat(createdUser.getRoles()).containsExactly(tenantUserManagementProperties.getKcRoleMapping().getAllRoles().toArray(new String[0]));
|
||||
|
||||
userClient.deleteUsers(List.of(createdUser.getUserId()));
|
||||
@ -78,4 +89,49 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
assertThat(allUsers).hasSize(1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void testResetPassword() {
|
||||
|
||||
testTenantService.createTestTenantIfNotExists("test-password-reset", minioPort);
|
||||
TenantContext.setTenantId("test-password-reset");
|
||||
|
||||
var createUserRequest = new CreateUserRequest();
|
||||
createUserRequest.setEmail("less.super.user.1@knecon.com");
|
||||
createUserRequest.setUsername(createUserRequest.getEmail());
|
||||
createUserRequest.setRoles(Set.of("LESS_SUPER_USER"));
|
||||
var createdUser1 = userClient.createUser(createUserRequest);
|
||||
|
||||
createUserRequest = new CreateUserRequest();
|
||||
createUserRequest.setEmail("less.super.user.2@knecon.com");
|
||||
createUserRequest.setUsername(createUserRequest.getEmail());
|
||||
createUserRequest.setRoles(Set.of("LESS_SUPER_USER"));
|
||||
var createdUser2 = userClient.createUser(createUserRequest);
|
||||
|
||||
//reset password as super-user for less-super-user
|
||||
userClient.resetPassword(createdUser1.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
|
||||
|
||||
//reset password as super-user for less-super-user
|
||||
userClient.resetPassword(createdUser2.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
|
||||
|
||||
//authenticate as less-super-user
|
||||
tokenService.setUser("less.super.user.1@knecon.com", "Secret@secured!23");
|
||||
|
||||
//reset password as less-super-user for less-super-user
|
||||
userClient.resetPassword(createdUser2.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!2345").build());
|
||||
|
||||
var allUsers = userClient.getAllUsers(true);
|
||||
var initialSuperUser = allUsers.stream().filter(u -> u.getEmail().equalsIgnoreCase("test@fforesight.com")).findAny().get();
|
||||
try {
|
||||
//reset password as less-super-user for super-user
|
||||
userClient.resetPassword(initialSuperUser.getUserId(), ResetPasswordRequest.builder().password("ShouldNotWork@123").build());
|
||||
fail("Should not be allowed to reset password of higher ranking user");
|
||||
} catch (FeignException e) {
|
||||
// forbidden to reset password of higher ranking user
|
||||
assertThat(e.status()).isEqualTo(403);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -4,13 +4,6 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
@ -26,6 +19,11 @@ import com.knecon.fforesight.feigntestclients.internal.InternalTenantsClient;
|
||||
import com.knecon.fforesight.tenantusermanagement.TenantUserManagementServiceApplication;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.KeyCloakRoleManagerService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.RealmService;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
|
||||
@ActiveProfiles(profiles = "taas")
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ -49,7 +47,7 @@ public class TenantSyncUtils {
|
||||
KeyCloakRoleManagerService keyCloakRoleManagerService;
|
||||
|
||||
|
||||
// @Test
|
||||
// @Test
|
||||
// @Disabled
|
||||
public void syncTenant() {
|
||||
|
||||
|
||||
@ -12,13 +12,11 @@ import com.knecon.fforesight.feigntestclients.external.TenantsClient;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantcommons.model.DatabaseConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.S3StorageConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.SearchConnection;
|
||||
import com.knecon.fforesight.tenantusermanagement.api.internal.InternalTenantsResource;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SearchConnectionRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantUser;
|
||||
import com.knecon.fforesight.testcontainers.SpringPostgreSQLTestContainer;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
||||
@ -46,19 +44,6 @@ public class TestTenantService {
|
||||
}
|
||||
|
||||
|
||||
public void createTestTenantWithoutStorageIfNotExist(String testTenantId) {
|
||||
|
||||
try {
|
||||
var tenantExists = internalTenantsResource.getTenant(testTenantId);
|
||||
assertThat(tenantExists.getGuid()).isNotBlank();
|
||||
|
||||
} catch (Exception e) {
|
||||
// not found
|
||||
createUser(testTenantId, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void createUser(String testTenantId, int actualPort, boolean withStorage) {
|
||||
// not found
|
||||
TenantRequest tenantRequest;
|
||||
@ -106,4 +91,17 @@ public class TestTenantService {
|
||||
assertThat(tenant.getGuid()).isNotBlank();
|
||||
}
|
||||
|
||||
|
||||
public void createTestTenantWithoutStorageIfNotExist(String testTenantId) {
|
||||
|
||||
try {
|
||||
var tenantExists = internalTenantsResource.getTenant(testTenantId);
|
||||
assertThat(tenantExists.getGuid()).isNotBlank();
|
||||
|
||||
} catch (Exception e) {
|
||||
// not found
|
||||
createUser(testTenantId, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,19 +6,18 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.ws.rs.BadRequestException;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -30,6 +29,7 @@ public class TokenService {
|
||||
private String password;
|
||||
private String accessToken;
|
||||
|
||||
|
||||
@SuppressWarnings("PMD")
|
||||
public void setUser(String username, String password) {
|
||||
|
||||
@ -42,7 +42,7 @@ public class TokenService {
|
||||
@SneakyThrows
|
||||
public String getToken() {
|
||||
|
||||
if(TenantContext.getTenantId() == null){
|
||||
if (TenantContext.getTenantId() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -67,9 +67,9 @@ public class TokenService {
|
||||
try {
|
||||
accessToken = tokenClient.tokenManager().getAccessTokenString();
|
||||
return accessToken;
|
||||
}catch (BadRequestException e){
|
||||
} catch (BadRequestException e) {
|
||||
var response = IOUtils.toString(new InputStreamReader((InputStream) e.getResponse().getEntity()));
|
||||
log.warn("Exception getting token: {}",response, e);
|
||||
log.warn("Exception getting token: {}", response, e);
|
||||
throw e;
|
||||
} finally {
|
||||
tokenClient.close();
|
||||
|
||||
@ -123,6 +123,23 @@ fforesight:
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- name: LESS_SUPER_USER
|
||||
set-by-default: true
|
||||
rank: 10
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
access-token-life-span: 86400
|
||||
application-name: tenant-user-management
|
||||
application-client-id: tenant-user-management
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user