diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java index 1e4dbfb27..91d707c67 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java @@ -290,6 +290,9 @@ public class SecurityManagedConfiguration { @Autowired private SecurityProperties springSecurityProperties; + @Autowired + private SystemSecurityContext systemSecurityContext; + @Override protected void configure(final HttpSecurity http) throws Exception { @@ -318,9 +321,8 @@ public class SecurityManagedConfiguration { userAuthenticationFilter.destroy(); } }, RequestHeaderAuthenticationFilter.class) - .addFilterAfter( - new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement), - SessionManagementFilter.class) + .addFilterAfter(new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement, + systemSecurityContext), SessionManagementFilter.class) .authorizeRequests().anyRequest().authenticated() .antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/admin/**") .hasAnyAuthority(SpPermission.SYSTEM_ADMIN); @@ -522,6 +524,9 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends @Autowired private SystemManagement systemManagement; + @Autowired + private SystemSecurityContext systemSecurityContext; + @Override public void onAuthenticationSuccess(final Authentication authentication) throws Exception { @@ -536,7 +541,9 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends // LoginView. This needs to be changed with the update of // vaadin4spring 0.0.7 because it // has been fixed. - systemManagement.getTenantMetadata("DEFAULT"); + final String defaultTenant = "DEFAULT"; + systemSecurityContext.runAsSystemAsTenant(() -> systemManagement.getTenantMetadata(defaultTenant), + defaultTenant); } super.onAuthenticationSuccess(authentication); @@ -550,11 +557,13 @@ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter { private final TenantAware tenantAware; private final SystemManagement systemManagement; + private final SystemSecurityContext systemSecurityContext; AuthenticationSuccessTenantMetadataCreationFilter(final TenantAware tenantAware, - final SystemManagement systemManagement) { + final SystemManagement systemManagement, final SystemSecurityContext systemSecurityContext) { this.tenantAware = tenantAware; this.systemManagement = systemManagement; + this.systemSecurityContext = systemSecurityContext; } @Override @@ -569,7 +578,8 @@ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter { final String currentTenant = tenantAware.getCurrentTenant(); if (currentTenant != null) { // lazy initialize tenant meta data after successful authentication - systemManagement.getTenantMetadata(currentTenant); + systemSecurityContext.runAsSystemAsTenant(() -> systemManagement.getTenantMetadata(currentTenant), + currentTenant); } chain.doFilter(request, response); diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java index 31ec37c58..ba5e3d2f6 100644 --- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java +++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java @@ -8,6 +8,10 @@ */ package org.eclipse.hawkbit.ddi.rest.resource; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE; import static org.fest.assertions.api.Assertions.assertThat; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.startsWith; @@ -23,7 +27,6 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.hawkbit.im.authentication.SpPermission; -import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; @@ -57,7 +60,8 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD @Test @Description("Ensures that targets cannot be created e.g. in plug'n play scenarios when tenant does not exists but can be created if the tenant exists.") - @WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true, authorities = "ROLE_CONTROLLER", autoCreateTenant = false) + @WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true, authorities = { CONTROLLER_ROLE, + SYSTEM_ROLE }, autoCreateTenant = false) public void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception { mvc.perform(get("/default-tenant/", tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print()) @@ -91,13 +95,11 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD // make a poll, audit information should not be changed, run as // controller principal! - securityRule.runAs( - WithSpringAuthorityRule.withUser("controller", SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS), () -> { - mvc.perform( - get("/{tenant}/controller/v1/" + knownTargetControllerId, tenantAware.getCurrentTenant())) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); - return null; - }); + securityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { + mvc.perform(get("/{tenant}/controller/v1/" + knownTargetControllerId, tenantAware.getCurrentTenant())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); + return null; + }); // verify that audit information has not changed final Target targetVerify = targetManagement.findTargetByControllerID(knownTargetControllerId); @@ -143,22 +145,19 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD @Description("Ensures that tenant specific polling time, which is saved in the db, is delivered to the controller.") @WithUser(principal = "knownpricipal", allSpPermissions = false) public void pollWithModifiedGloablPollingTime() throws Exception { - securityRule.runAs( - WithSpringAuthorityRule.withUser("tenantadmin", SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION), - () -> { - tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL, - "00:02:00"); - return null; - }); + securityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION), () -> { + tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL, + "00:02:00"); + return null; + }); - securityRule.runAs( - WithSpringAuthorityRule.withUser("controller", SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS), () -> { - mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) - .andExpect(content().contentType(MediaTypes.HAL_JSON)) - .andExpect(jsonPath("$config.polling.sleep", equalTo("00:02:00"))); - return null; - }); + securityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { + mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaTypes.HAL_JSON)) + .andExpect(jsonPath("$config.polling.sleep", equalTo("00:02:00"))); + return null; + }); } @Test diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java index e99a33c5f..e872e0221 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java @@ -39,6 +39,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetWithActionType; +import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,6 +82,9 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { @Autowired private DistributionSetManagement distributionSetManagement; + @Autowired + private SystemSecurityContext systemSecurityContext; + @Override public ResponseEntity> getDistributionSets( @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam, @@ -119,8 +123,9 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { LOG.debug("creating {} distribution sets", sets.size()); // set default Ds type if ds type is null - sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(this.systemManagement - .getTenantMetadata(this.currentTenant.getCurrentTenant()).getDefaultDsType().getKey())); + final String defaultDsKey = systemSecurityContext.runAsSystem(() -> this.systemManagement + .getTenantMetadata(this.currentTenant.getCurrentTenant()).getDefaultDsType().getKey()); + sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(defaultDsKey)); final Iterable createdDSets = this.distributionSetManagement .createDistributionSets(MgmtDistributionSetMapper.dsFromRequest(sets, this.softwareManagement, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SystemManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SystemManagementTest.java index a9f004a73..ac2b30d23 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SystemManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SystemManagementTest.java @@ -14,10 +14,10 @@ import java.io.ByteArrayInputStream; import java.util.List; import java.util.Random; +import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; -import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.report.model.TenantUsage; import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule; import org.junit.Test; @@ -30,15 +30,6 @@ import ru.yandex.qatools.allure.annotations.Stories; @Stories("System Management") public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB { - @Test - @Description("Ensures that you can create a tenant without setting the necessary security context which holds a current tenant") - public void createInitialTenantWithoutSecurityContext() { - securityRule.clear(); - final String tenantToBeCreated = "newTenantToCreate"; - final TenantMetaData tenantMetadata = systemManagement.getTenantMetadata(tenantToBeCreated); - assertThat(tenantMetadata).isNotNull(); - } - @Test @Description("Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in") public void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() throws Exception { @@ -109,26 +100,27 @@ public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB for (int i = 0; i < tenants; i++) { final String tenantname = "tenant" + i; - securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname), () -> { - systemManagement.getTenantMetadata(tenantname); - if (artifactSize > 0) { - createTestArtifact(random); - createDeletedTestArtifact(random); - } - if (targets > 0) { - final List createdTargets = createTestTargets(targets); - if (updates > 0) { - for (int x = 0; x < updates; x++) { - final DistributionSet ds = testdataFactory.createDistributionSet("to be deployed" + x, - true); - - deploymentManagement.assignDistributionSet(ds, createdTargets); + securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname, true, true, + SpringEvalExpressions.SYSTEM_ROLE), () -> { + systemManagement.getTenantMetadata(tenantname); + if (artifactSize > 0) { + createTestArtifact(random); + createDeletedTestArtifact(random); } - } - } + if (targets > 0) { + final List createdTargets = createTestTargets(targets); + if (updates > 0) { + for (int x = 0; x < updates; x++) { + final DistributionSet ds = testdataFactory + .createDistributionSet("to be deployed" + x, true); - return null; - }); + deploymentManagement.assignDistributionSet(ds, createdTargets); + } + } + } + + return null; + }); } return random;