From 046ec2b2ec0f0348487e9a5f9b492e84d4f61e51 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Mon, 1 Aug 2016 17:22:21 +0200 Subject: [PATCH 01/22] add preauthorize to system management Signed-off-by: Michael Hirsch --- .../hawkbit/repository/SystemManagement.java | 5 +++++ .../test/util/WithSpringAuthorityRule.java | 21 +++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java index a44b13d92..e30009258 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java @@ -61,6 +61,9 @@ public interface SystemManagement { /** * @return {@link TenantMetaData} of {@link TenantAware#getCurrentTenant()} */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + + SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR + + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) TenantMetaData getTenantMetadata(); /** @@ -77,6 +80,7 @@ public interface SystemManagement { * to retrieve data for * @return {@link TenantMetaData} of given tenant */ + @PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE) TenantMetaData getTenantMetadata(@NotNull String tenant); /** @@ -86,6 +90,7 @@ public interface SystemManagement { * to update * @return updated {@link TenantMetaData} entity */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) TenantMetaData updateTenantMetadata(@NotNull TenantMetaData metaData); } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java index a2bc90555..357ec5f69 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.concurrent.Callable; import org.eclipse.hawkbit.im.authentication.SpPermission; +import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.repository.jpa.model.helper.SystemManagementHolder; import org.junit.rules.TestRule; @@ -56,10 +57,10 @@ public class WithSpringAuthorityRule implements TestRule { annotation = description.getTestClass().getAnnotation(WithUser.class); } if (annotation != null) { - setSecurityContext(annotation); if (annotation.autoCreateTenant()) { - SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(annotation.tenantId()); + createTenant(annotation.tenantId()); } + setSecurityContext(annotation); } return oldContext; } @@ -158,7 +159,7 @@ public class WithSpringAuthorityRule implements TestRule { final SecurityContext oldContext = SecurityContextHolder.getContext(); setSecurityContext(withUser); if (withUser.autoCreateTenant()) { - SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(withUser.tenantId()); + createTenant(withUser.tenantId()); } try { return callable.call(); @@ -166,6 +167,18 @@ public class WithSpringAuthorityRule implements TestRule { after(oldContext); } } + + private void createTenant(final String tenantId) throws Exception { + final SecurityContext oldContext = SecurityContextHolder.getContext(); + setSecurityContext(privilegedUser()); + try + { + SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(tenantId); + }finally + { + after(oldContext); + } + } public static WithUser withUser(final String principal, final String... authorities) { return withUserAndTenant(principal, "default", true, true, authorities); @@ -254,7 +267,7 @@ public class WithSpringAuthorityRule implements TestRule { @Override public String[] authorities() { - return new String[] { "ROLE_CONTROLLER" }; + return new String[] { "ROLE_CONTROLLER", "ROLE_SYSTEM_CODE" }; } @Override From fc4747083ca32a40746f5dd689c3fea194588221 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 2 Aug 2016 12:51:08 +0200 Subject: [PATCH 02/22] Use system role where necessary to invoke the getTenantMetadata method Signed-off-by: Michael Hirsch --- .../SecurityManagedConfiguration.java | 22 ++++++--- .../rest/resource/DdiRootControllerTest.java | 47 +++++++++--------- .../resource/MgmtDistributionSetResource.java | 9 +++- .../repository/jpa/SystemManagementTest.java | 48 ++++++++----------- 4 files changed, 66 insertions(+), 60 deletions(-) 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; From 9c75ae308d4d96f6ed0842d4e6ae3a64376f6b28 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 2 Aug 2016 13:01:31 +0200 Subject: [PATCH 03/22] reduce usage of getTenantMetadata(String) Signed-off-by: Michael Hirsch --- .../SecurityManagedConfiguration.java | 25 +++++++------------ .../resource/MgmtDistributionSetResource.java | 8 ++---- .../test/util/AbstractIntegrationTest.java | 5 +++- 3 files changed, 15 insertions(+), 23 deletions(-) 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 91d707c67..e05bdb7f1 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 @@ -321,7 +321,7 @@ public class SecurityManagedConfiguration { userAuthenticationFilter.destroy(); } }, RequestHeaderAuthenticationFilter.class) - .addFilterAfter(new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement, + .addFilterAfter(new AuthenticationSuccessTenantMetadataCreationFilter(systemManagement, systemSecurityContext), SessionManagementFilter.class) .authorizeRequests().anyRequest().authenticated() .antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/admin/**") @@ -531,8 +531,8 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends public void onAuthenticationSuccess(final Authentication authentication) throws Exception { if (authentication.getClass().equals(TenantUserPasswordAuthenticationToken.class)) { - systemManagement - .getTenantMetadata(((TenantUserPasswordAuthenticationToken) authentication).getTenant().toString()); + systemSecurityContext.runAsSystemAsTenant(() -> systemManagement.getTenantMetadata(), + ((TenantUserPasswordAuthenticationToken) authentication).getTenant().toString()); } else if (authentication.getClass().equals(UsernamePasswordAuthenticationToken.class)) { // TODO: vaadin4spring-ext-security does not give us the // fullyAuthenticatedToken @@ -542,8 +542,7 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends // vaadin4spring 0.0.7 because it // has been fixed. final String defaultTenant = "DEFAULT"; - systemSecurityContext.runAsSystemAsTenant(() -> systemManagement.getTenantMetadata(defaultTenant), - defaultTenant); + systemSecurityContext.runAsSystemAsTenant(() -> systemManagement.getTenantMetadata(), defaultTenant); } super.onAuthenticationSuccess(authentication); @@ -555,13 +554,11 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends */ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter { - private final TenantAware tenantAware; private final SystemManagement systemManagement; private final SystemSecurityContext systemSecurityContext; - AuthenticationSuccessTenantMetadataCreationFilter(final TenantAware tenantAware, - final SystemManagement systemManagement, final SystemSecurityContext systemSecurityContext) { - this.tenantAware = tenantAware; + AuthenticationSuccessTenantMetadataCreationFilter(final SystemManagement systemManagement, + final SystemSecurityContext systemSecurityContext) { this.systemManagement = systemManagement; this.systemSecurityContext = systemSecurityContext; } @@ -575,14 +572,10 @@ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter { public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { - final String currentTenant = tenantAware.getCurrentTenant(); - if (currentTenant != null) { - // lazy initialize tenant meta data after successful authentication - systemSecurityContext.runAsSystemAsTenant(() -> systemManagement.getTenantMetadata(currentTenant), - currentTenant); - } - + // lazy initialize tenant meta data after successful authentication + systemSecurityContext.runAsSystem(() -> systemManagement.getTenantMetadata()); chain.doFilter(request, response); + } @Override 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 e872e0221..721995d88 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 @@ -40,7 +40,6 @@ 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; import org.springframework.beans.factory.annotation.Autowired; @@ -73,9 +72,6 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { @Autowired private SystemManagement systemManagement; - @Autowired - private TenantAware currentTenant; - @Autowired private EntityFactory entityFactory; @@ -123,8 +119,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { LOG.debug("creating {} distribution sets", sets.size()); // set default Ds type if ds type is null - final String defaultDsKey = systemSecurityContext.runAsSystem(() -> this.systemManagement - .getTenantMetadata(this.currentTenant.getCurrentTenant()).getDefaultDsType().getKey()); + final String defaultDsKey = systemSecurityContext + .runAsSystem(() -> this.systemManagement.getTenantMetadata().getDefaultDsType().getKey()); sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(defaultDsKey)); final Iterable createdDSets = this.distributionSetManagement diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java index 3d09fabc3..c12a3b0b3 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java @@ -8,6 +8,9 @@ */ package org.eclipse.hawkbit.repository.test.util; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE; + import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ControllerManagement; @@ -58,7 +61,7 @@ import org.springframework.web.context.WebApplicationContext; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ActiveProfiles({ "test" }) -@WithUser(principal = "bumlux", allSpPermissions = true, authorities = "ROLE_CONTROLLER") +@WithUser(principal = "bumlux", allSpPermissions = true, authorities = { CONTROLLER_ROLE, SYSTEM_ROLE }) @SpringApplicationConfiguration(classes = { TestConfiguration.class }) // destroy the context after each test class because otherwise we get problem // when context is From 041dd3bb7af7b6485c0602f61f3ad1bc23176465 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 2 Aug 2016 14:05:24 +0200 Subject: [PATCH 04/22] don't allow anonymous login on rest-api Signed-off-by: Michael Hirsch --- .../security/SecurityManagedConfiguration.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 e05bdb7f1..e6eb1d159 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 @@ -73,6 +73,7 @@ import org.springframework.security.config.annotation.web.servlet.configuration. import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; @@ -328,6 +329,7 @@ public class SecurityManagedConfiguration { .hasAnyAuthority(SpPermission.SYSTEM_ADMIN); httpSec.httpBasic().and().exceptionHandling().authenticationEntryPoint(basicAuthEntryPoint); + httpSec.anonymous().disable(); } } @@ -573,7 +575,10 @@ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter { throws IOException, ServletException { // lazy initialize tenant meta data after successful authentication - systemSecurityContext.runAsSystem(() -> systemManagement.getTenantMetadata()); + final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null && authentication.isAuthenticated()) { + systemSecurityContext.runAsSystem(() -> systemManagement.getTenantMetadata()); + } chain.doFilter(request, response); } From 2ba9fd135d54e76d1a605d86f2215be5d786b811 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 3 Aug 2016 09:08:03 +0200 Subject: [PATCH 05/22] Add missing PreAuthorize annotation to secure methods and write unit test Signed-off-by: Michael Hirsch --- .../hawkbit-repository-api/pom.xml | 65 ++++++---- .../repository/ControllerManagement.java | 2 + .../repository/SoftwareManagement.java | 1 + ...gementMethodPreAuthorizeAnnotatedTest.java | 121 ++++++++++++++++++ .../repository/jpa/MethodSecurityUtil.java | 63 --------- .../im/authentication/SpPermission.java | 8 ++ 6 files changed, 170 insertions(+), 90 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java delete mode 100644 hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/MethodSecurityUtil.java diff --git a/hawkbit-repository/hawkbit-repository-api/pom.xml b/hawkbit-repository/hawkbit-repository-api/pom.xml index 050a9a070..cfd45998c 100644 --- a/hawkbit-repository/hawkbit-repository-api/pom.xml +++ b/hawkbit-repository/hawkbit-repository-api/pom.xml @@ -1,24 +1,16 @@ - + - 4.0.0 - - org.eclipse.hawkbit - hawkbit-repository - 0.2.0-SNAPSHOT - - hawkbit-repository-api - hawkBit :: Repository API - - + 4.0.0 + + org.eclipse.hawkbit + hawkbit-repository + 0.2.0-SNAPSHOT + + hawkbit-repository-api + hawkBit :: Repository API + + org.eclipse.hawkbit hawkbit-security-core @@ -36,14 +28,33 @@ cz.jirutka.rsql rsql-parser - + org.springframework.hateoas spring-hateoas - - org.springframework.boot - spring-boot-configuration-processor - true - - + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + ru.yandex.qatools.allure + allure-junit-adaptor + test + + + org.easytesting + fest-assert-core + test + + + org.easytesting + fest-assert + test + + \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index e5dcb8f74..f06621fd4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -183,6 +183,8 @@ public interface ControllerManagement { * @return the security context of the target, in case no target exists for * the given controllerId {@code null} is returned */ + @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER + SpringEvalExpressions.HAS_AUTH_OR + + SpringEvalExpressions.HAS_AUTH_READ_TARGET_SEC_TOKEN) String getSecurityTokenByControllerId(@NotEmpty String controllerId); /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java index 0934e871e..bc3c50004 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java @@ -340,6 +340,7 @@ public interface SoftwareManagement { * to search for * @return {@link List} of found {@link SoftwareModule}s */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) List findSoftwareModulesById(@NotEmpty Collection ids); /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java new file mode 100644 index 000000000..1ccbb8bc5 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.repository; + +import static org.fest.assertions.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + +import org.junit.Test; +import org.springframework.security.access.prepost.PreAuthorize; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +@Features("Unit Tests - Repository") +@Stories("Security Test") +public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { + + private static final Set METHOD_SECURITY_EXCLUSION = new HashSet<>(); + + static { + METHOD_SECURITY_EXCLUSION.add(getMethod(SystemManagement.class, "currentTenant")); + } + + @Test + @Description("Verfies that repository methods are @PreAuthorize annotated") + public void repositoryManagementMethodsArePreAuthorizedAnnotated() + throws ClassNotFoundException, URISyntaxException, IOException { + final List> findInterfacesInPackage = findInterfacesInPackage(getClass().getPackage(), + Pattern.compile(".*Management")); + for (final Class interfaceToCheck : findInterfacesInPackage) { + assertDeclaredMethodsContainsPreAuthorizeAnnotaions(interfaceToCheck); + } + } + + /** + * asserts that the given methods are annotated with the + * {@link PreAuthorize} annotation for security. Inherited methods are not + * checked. The following methods are excluded due inherited from + * {@link Object}, like equals() or toString(). + * + * @param clazz + * the class to retrieve the public declared methods + */ + private static void assertDeclaredMethodsContainsPreAuthorizeAnnotaions(final Class clazz) { + final Method[] declaredMethods = clazz.getDeclaredMethods(); + for (final Method method : declaredMethods) { + if (!METHOD_SECURITY_EXCLUSION.contains(method) && !method.isSynthetic() + && Modifier.isPublic(method.getModifiers())) { + final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class); + assertThat(annotation).as("The public method " + method.getName() + " in class " + clazz.getName() + + " is not annoated with @PreAuthorize, security leak?").isNotNull(); + } + } + } + + /** + * Finds all interfaces in a given packages which matches the given filter. + * + * @param p + * the package to search for interfaces in + * @param includeFilter + * the pattern which interfaces class names should be included + * @return a list of loaded interfaces in a specific package and matches the + * given filter + * @throws URISyntaxException + * @throws IOException + * @throws ClassNotFoundException + */ + private List> findInterfacesInPackage(final Package p, final Pattern includeFilter) + throws URISyntaxException, IOException, ClassNotFoundException { + final List> interfacesToReturn = new ArrayList<>(); + final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + final Enumeration resources = classLoader.getResources(p.getName().replace(".", "/")); + while (resources.hasMoreElements()) { + final File packageDirectory = new File(new URI(resources.nextElement().toString()).getPath()); + final File[] filesInPackage = packageDirectory.listFiles(); + for (final File classFile : filesInPackage) { + final String classNameWithExtension = classFile.getName(); + final int indexOfExtension = classNameWithExtension.indexOf(".class"); + if (indexOfExtension > 0) { + final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); + if (includeFilter.matcher(classNameWithoutExtension).matches()) { + final Class classInPackage = Class.forName(p.getName() + "." + classNameWithoutExtension); + if (classInPackage.isInterface()) { + interfacesToReturn.add(classInPackage); + } + } + } + } + } + return interfacesToReturn; + } + + private static Method getMethod(final Class clazz, final String methodName, final Class... parameterTypes) { + try { + return clazz.getMethod(methodName, parameterTypes); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException(e.getMessage(), e); + } + } +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/MethodSecurityUtil.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/MethodSecurityUtil.java deleted file mode 100644 index 032289e87..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/MethodSecurityUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - */ -package org.eclipse.hawkbit.repository.jpa; - -import static org.fest.assertions.Assertions.assertThat; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashSet; -import java.util.Set; - -import org.springframework.security.access.prepost.PreAuthorize; - -public class MethodSecurityUtil { - - private static final Set METHOD_SECURITY_EXCLUSION = new HashSet<>(); - - static { - METHOD_SECURITY_EXCLUSION.add("equals"); - METHOD_SECURITY_EXCLUSION.add("toString"); - METHOD_SECURITY_EXCLUSION.add("hashCode"); - METHOD_SECURITY_EXCLUSION.add("clone"); - METHOD_SECURITY_EXCLUSION.add("setEnvironment"); - // this method shouldn't be public on the DeploymentManagemeht but it is - METHOD_SECURITY_EXCLUSION.add("setOverrideObsoleteUpdateActions"); - METHOD_SECURITY_EXCLUSION.add("isOverrideObsoleteUpdateActions"); - // this method must be public accessible without security because it's - // necessary to acccess - // the security-token of a target without being authenticated because - // the security-token is - // the authentication process - // ControllerManagement#getSecurityTokenByControllerId() - METHOD_SECURITY_EXCLUSION.add("getSecurityTokenByControllerId"); - } - - /** - * asserts that the given methods are annotated with the - * {@link PreAuthorize} annotation for security. Inherited methods are not - * checked. The following methods are excluded due inherited from - * {@link Object}, like equals() or toString(). - * - * @param clazz - * the class to retrieve the public declared methods - */ - public static void assertDeclaredMethodsContainsPreAuthorizeAnnotaions(final Class clazz) { - final Method[] declaredMethods = clazz.getDeclaredMethods(); - for (final Method method : declaredMethods) { - if (!METHOD_SECURITY_EXCLUSION.contains(method.getName()) && !method.isSynthetic() - && Modifier.isPublic(method.getModifiers())) { - final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class); - assertThat(annotation).as( - "The public method " + method.getName() + " is not annoated with @PreAuthorize, security leak?") - .isNotNull(); - } - } - } -} diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java index daf5f0dd9..783f27b7e 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java @@ -290,6 +290,14 @@ public final class SpPermission { public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE; + /** + * Spring security eval hasAuthority expression to check if spring + * context contains {@link SpPermission#READ_TARGET_SEC_TOKEN} or + * {@link #IS_SYSTEM_CODE}. + */ + public static final String HAS_AUTH_READ_TARGET_SEC_TOKEN = HAS_AUTH_PREFIX + READ_TARGET_SEC_TOKEN + + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE; + /** * Spring security eval hasAuthority expression to check if spring * context contains {@link SpPermission#CREATE_TARGET} or From 2965c93083f315ee2e35c81b479173cd0c9e9542 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 3 Aug 2016 09:24:28 +0200 Subject: [PATCH 06/22] fix unit test Signed-off-by: Michael Hirsch --- ...gementMethodPreAuthorizeAnnotatedTest.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java index 1ccbb8bc5..8de225dcd 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java @@ -47,6 +47,8 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { throws ClassNotFoundException, URISyntaxException, IOException { final List> findInterfacesInPackage = findInterfacesInPackage(getClass().getPackage(), Pattern.compile(".*Management")); + + assertThat(findInterfacesInPackage).isNotEmpty(); for (final Class interfaceToCheck : findInterfacesInPackage) { assertDeclaredMethodsContainsPreAuthorizeAnnotaions(interfaceToCheck); } @@ -92,17 +94,21 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); final Enumeration resources = classLoader.getResources(p.getName().replace(".", "/")); while (resources.hasMoreElements()) { - final File packageDirectory = new File(new URI(resources.nextElement().toString()).getPath()); - final File[] filesInPackage = packageDirectory.listFiles(); - for (final File classFile : filesInPackage) { - final String classNameWithExtension = classFile.getName(); - final int indexOfExtension = classNameWithExtension.indexOf(".class"); - if (indexOfExtension > 0) { - final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); - if (includeFilter.matcher(classNameWithoutExtension).matches()) { - final Class classInPackage = Class.forName(p.getName() + "." + classNameWithoutExtension); - if (classInPackage.isInterface()) { - interfacesToReturn.add(classInPackage); + final String uriPath = new URI(resources.nextElement().toString()).getPath(); + if (uriPath != null) { + final File packageDirectory = new File(uriPath); + final File[] filesInPackage = packageDirectory.listFiles(); + for (final File classFile : filesInPackage) { + final String classNameWithExtension = classFile.getName(); + final int indexOfExtension = classNameWithExtension.indexOf(".class"); + if (indexOfExtension > 0) { + final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); + if (includeFilter.matcher(classNameWithoutExtension).matches()) { + final Class classInPackage = Class + .forName(p.getName() + "." + classNameWithoutExtension); + if (classInPackage.isInterface()) { + interfacesToReturn.add(classInPackage); + } } } } From fca7ecbce4fe2bb0eb831e1eb7ce1974fe1be29a Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 3 Aug 2016 09:32:10 +0200 Subject: [PATCH 07/22] fix unit test Signed-off-by: Michael Hirsch --- ...gementMethodPreAuthorizeAnnotatedTest.java | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java index 8de225dcd..53b691c09 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java @@ -14,7 +14,6 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; @@ -94,21 +93,17 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); final Enumeration resources = classLoader.getResources(p.getName().replace(".", "/")); while (resources.hasMoreElements()) { - final String uriPath = new URI(resources.nextElement().toString()).getPath(); - if (uriPath != null) { - final File packageDirectory = new File(uriPath); - final File[] filesInPackage = packageDirectory.listFiles(); - for (final File classFile : filesInPackage) { - final String classNameWithExtension = classFile.getName(); - final int indexOfExtension = classNameWithExtension.indexOf(".class"); - if (indexOfExtension > 0) { - final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); - if (includeFilter.matcher(classNameWithoutExtension).matches()) { - final Class classInPackage = Class - .forName(p.getName() + "." + classNameWithoutExtension); - if (classInPackage.isInterface()) { - interfacesToReturn.add(classInPackage); - } + final File packageDirectory = new File(resources.nextElement().getFile()); + final File[] filesInPackage = packageDirectory.listFiles(); + for (final File classFile : filesInPackage) { + final String classNameWithExtension = classFile.getName(); + final int indexOfExtension = classNameWithExtension.indexOf(".class"); + if (indexOfExtension > 0) { + final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); + if (includeFilter.matcher(classNameWithoutExtension).matches()) { + final Class classInPackage = Class.forName(p.getName() + "." + classNameWithoutExtension); + if (classInPackage.isInterface()) { + interfacesToReturn.add(classInPackage); } } } From cd39f32c215fa93c0884f29d020dea1b4815872b Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 3 Aug 2016 09:49:57 +0200 Subject: [PATCH 08/22] fix unit test Signed-off-by: Michael Hirsch --- ...gementMethodPreAuthorizeAnnotatedTest.java | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java index 53b691c09..3f77a2f38 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; @@ -51,6 +52,10 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { for (final Class interfaceToCheck : findInterfacesInPackage) { assertDeclaredMethodsContainsPreAuthorizeAnnotaions(interfaceToCheck); } + + // all exclusion should be used, otherwise the method exlusion should be + // cleaned up again + assertThat(METHOD_SECURITY_EXCLUSION).isEmpty(); } /** @@ -65,12 +70,15 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { private static void assertDeclaredMethodsContainsPreAuthorizeAnnotaions(final Class clazz) { final Method[] declaredMethods = clazz.getDeclaredMethods(); for (final Method method : declaredMethods) { - if (!METHOD_SECURITY_EXCLUSION.contains(method) && !method.isSynthetic() - && Modifier.isPublic(method.getModifiers())) { - final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class); - assertThat(annotation).as("The public method " + method.getName() + " in class " + clazz.getName() - + " is not annoated with @PreAuthorize, security leak?").isNotNull(); + final boolean methodExcluded = METHOD_SECURITY_EXCLUSION.contains(method); + if (methodExcluded || method.isSynthetic() || Modifier.isPublic(method.getModifiers())) { + // skip method because it should be excluded + METHOD_SECURITY_EXCLUSION.remove(method); + continue; } + final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class); + assertThat(annotation).as("The public method " + method.getName() + " in class " + clazz.getName() + + " is not annoated with @PreAuthorize, security leak?").isNotNull(); } } @@ -93,17 +101,21 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); final Enumeration resources = classLoader.getResources(p.getName().replace(".", "/")); while (resources.hasMoreElements()) { - final File packageDirectory = new File(resources.nextElement().getFile()); - final File[] filesInPackage = packageDirectory.listFiles(); - for (final File classFile : filesInPackage) { - final String classNameWithExtension = classFile.getName(); - final int indexOfExtension = classNameWithExtension.indexOf(".class"); - if (indexOfExtension > 0) { - final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); - if (includeFilter.matcher(classNameWithoutExtension).matches()) { - final Class classInPackage = Class.forName(p.getName() + "." + classNameWithoutExtension); - if (classInPackage.isInterface()) { - interfacesToReturn.add(classInPackage); + final String uriPath = new URI(resources.nextElement().toString()).getPath(); + if (uriPath != null) { + final File packageDirectory = new File(uriPath); + final File[] filesInPackage = packageDirectory.listFiles(); + for (final File classFile : filesInPackage) { + final String classNameWithExtension = classFile.getName(); + final int indexOfExtension = classNameWithExtension.indexOf(".class"); + if (indexOfExtension > 0) { + final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); + if (includeFilter.matcher(classNameWithoutExtension).matches()) { + final Class classInPackage = Class + .forName(p.getName() + "." + classNameWithoutExtension); + if (classInPackage.isInterface()) { + interfacesToReturn.add(classInPackage); + } } } } From a12b10cd14bd028b8bede36063d57934f0493205 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Thu, 4 Aug 2016 08:51:30 +0200 Subject: [PATCH 09/22] fix license header Signed-off-by: Michael Hirsch --- hawkbit-repository/hawkbit-repository-api/pom.xml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/pom.xml b/hawkbit-repository/hawkbit-repository-api/pom.xml index cfd45998c..0a3f541d9 100644 --- a/hawkbit-repository/hawkbit-repository-api/pom.xml +++ b/hawkbit-repository/hawkbit-repository-api/pom.xml @@ -1,5 +1,13 @@ - + 4.0.0 From 038538f89a2d4ed9a80e3dbbae6df58631cad2df Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Thu, 4 Aug 2016 12:26:28 +0200 Subject: [PATCH 10/22] extract to meanful method Signed-off-by: Michael Hirsch --- .../security/SecurityManagedConfiguration.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) 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 e6eb1d159..30ce9d808 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 @@ -573,14 +573,16 @@ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter { @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { + lazyCreateTenantMetadata(); + chain.doFilter(request, response); - // lazy initialize tenant meta data after successful authentication + } + + private void lazyCreateTenantMetadata() { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.isAuthenticated()) { systemSecurityContext.runAsSystem(() -> systemManagement.getTenantMetadata()); } - chain.doFilter(request, response); - } @Override From b1b9716cc561bae9b8792e9a00bf60c3c1162082 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Thu, 4 Aug 2016 12:41:13 +0200 Subject: [PATCH 11/22] refactor test code Signed-off-by: Michael Hirsch --- ...gementMethodPreAuthorizeAnnotatedTest.java | 76 ++++++++++++++----- 1 file changed, 55 insertions(+), 21 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java index 3f77a2f38..4971ed1c1 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.repository; import static org.fest.assertions.Assertions.assertThat; import java.io.File; +import java.io.FileFilter; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -97,31 +98,25 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { */ private List> findInterfacesInPackage(final Package p, final Pattern includeFilter) throws URISyntaxException, IOException, ClassNotFoundException { - final List> interfacesToReturn = new ArrayList<>(); final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); final Enumeration resources = classLoader.getResources(p.getName().replace(".", "/")); + final RegexIncludeInterfaceFileCollector regexIncludeInterfaceFileCollector = new RegexIncludeInterfaceFileCollector( + p, includeFilter); while (resources.hasMoreElements()) { - final String uriPath = new URI(resources.nextElement().toString()).getPath(); - if (uriPath != null) { - final File packageDirectory = new File(uriPath); - final File[] filesInPackage = packageDirectory.listFiles(); - for (final File classFile : filesInPackage) { - final String classNameWithExtension = classFile.getName(); - final int indexOfExtension = classNameWithExtension.indexOf(".class"); - if (indexOfExtension > 0) { - final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); - if (includeFilter.matcher(classNameWithoutExtension).matches()) { - final Class classInPackage = Class - .forName(p.getName() + "." + classNameWithoutExtension); - if (classInPackage.isInterface()) { - interfacesToReturn.add(classInPackage); - } - } - } - } - } + listFilesInPackage(resources.nextElement(), regexIncludeInterfaceFileCollector); } - return interfacesToReturn; + return regexIncludeInterfaceFileCollector.getInterfaceClasses(); + } + + private File[] listFilesInPackage(final URL resource, final RegexIncludeInterfaceFileCollector clazzCollector) + throws URISyntaxException { + final String packagePath = new URI(resource.toString()).getPath(); + if (packagePath != null) { + final File packageDirectory = new File(packagePath); + final File[] filesInPackage = packageDirectory.listFiles(clazzCollector); + return filesInPackage; + } + return new File[0]; } private static Method getMethod(final Class clazz, final String methodName, final Class... parameterTypes) { @@ -131,4 +126,43 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { throw new RuntimeException(e.getMessage(), e); } } + + private static final class RegexIncludeInterfaceFileCollector implements FileFilter { + + private final List> interfaceClasses = new ArrayList<>(); + private final Pattern includeFilter; + private final Package basePackage; + + public RegexIncludeInterfaceFileCollector(final Package basePackage, final Pattern pattern) { + this.basePackage = basePackage; + this.includeFilter = pattern; + } + + @Override + public boolean accept(final File pathname) { + final String classNameWithExtension = pathname.getName(); + final int indexOfExtension = classNameWithExtension.indexOf(".class"); + if (indexOfExtension == -1) { + return false; + } + final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); + if (!includeFilter.matcher(classNameWithoutExtension).matches()) { + return false; + } + + try { + final Class classInPackage = Class.forName(basePackage.getName() + "." + classNameWithoutExtension); + if (classInPackage.isInterface()) { + interfaceClasses.add(classInPackage); + } + } catch (final ClassNotFoundException e) { + // don't need to handle here + } + return false; + } + + public List> getInterfaceClasses() { + return interfaceClasses; + } + } } From f5d9cf19bb5f9adbb5d4c536314380d2ee49acbb Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Thu, 4 Aug 2016 13:30:53 +0200 Subject: [PATCH 12/22] return type is not used, method can be void Signed-off-by: Michael Hirsch --- ...RepositoryManagementMethodPreAuthorizeAnnotatedTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java index 4971ed1c1..a827b36e7 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java @@ -108,15 +108,13 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { return regexIncludeInterfaceFileCollector.getInterfaceClasses(); } - private File[] listFilesInPackage(final URL resource, final RegexIncludeInterfaceFileCollector clazzCollector) + private void listFilesInPackage(final URL resource, final RegexIncludeInterfaceFileCollector clazzCollector) throws URISyntaxException { final String packagePath = new URI(resource.toString()).getPath(); if (packagePath != null) { final File packageDirectory = new File(packagePath); - final File[] filesInPackage = packageDirectory.listFiles(clazzCollector); - return filesInPackage; + packageDirectory.listFiles(clazzCollector); } - return new File[0]; } private static Method getMethod(final Class clazz, final String methodName, final Class... parameterTypes) { From 303a668f1632cb6ea15f19422cfb24efe5a34733 Mon Sep 17 00:00:00 2001 From: Gaurav Date: Thu, 4 Aug 2016 17:36:28 +0200 Subject: [PATCH 13/22] Fix for the entity lock exception for unassign soft module from DS Signed-off-by: Gaurav --- .../SoftwareModuleDetailsTable.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java index 1af6aabe1..713beced1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java @@ -186,12 +186,19 @@ public class SoftwareModuleDetailsTable extends Table { private void unassignSW(final ClickEvent event, final DistributionSet distributionSet, final Set alreadyAssignedSwModules) { final SoftwareModule unAssignedSw = getSoftwareModule(event.getButton().getId(), alreadyAssignedSwModules); - final DistributionSet newDistributionSet = distributionSetManagement.unassignSoftwareModule(distributionSet, - unAssignedSw); - manageDistUIState.setLastSelectedEntity(DistributionSetIdName.generate(newDistributionSet)); - eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, newDistributionSet)); - eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION); - uiNotification.displaySuccess(i18n.get("message.sw.unassigned", unAssignedSw.getName())); + if (distributionSetManagement.isDistributionSetInUse(distributionSet)) { + uiNotification.displayValidationError( + String.format("Distribution set %s:%s is already assigned to targets and cannot be changed", + distributionSet.getName(), distributionSet.getVersion())); + } else { + final DistributionSet newDistributionSet = distributionSetManagement.unassignSoftwareModule(distributionSet, + unAssignedSw); + manageDistUIState.setLastSelectedEntity(DistributionSetIdName.generate(newDistributionSet)); + eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, newDistributionSet)); + eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION); + uiNotification.displaySuccess(i18n.get("message.sw.unassigned", unAssignedSw.getName())); + } + } private static boolean isSoftModAvaiableForSoftType(final Set swModulesSet, From 582ac22678fd2749461fcd9e6110840abec0a48c Mon Sep 17 00:00:00 2001 From: Gaurav Date: Thu, 4 Aug 2016 17:44:13 +0200 Subject: [PATCH 14/22] Formatted the code --- .../ui/common/detailslayout/SoftwareModuleDetailsTable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java index 713beced1..036b229df 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java @@ -198,7 +198,7 @@ public class SoftwareModuleDetailsTable extends Table { eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION); uiNotification.displaySuccess(i18n.get("message.sw.unassigned", unAssignedSw.getName())); } - + } private static boolean isSoftModAvaiableForSoftType(final Set swModulesSet, From f964f7c0c6e2b87b80bd49446e6ee51c7d07a687 Mon Sep 17 00:00:00 2001 From: Gaurav Date: Thu, 4 Aug 2016 17:44:13 +0200 Subject: [PATCH 15/22] Formatted the code Signed-off-by: Gaurav --- .../ui/common/detailslayout/SoftwareModuleDetailsTable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java index 713beced1..036b229df 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java @@ -198,7 +198,7 @@ public class SoftwareModuleDetailsTable extends Table { eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION); uiNotification.displaySuccess(i18n.get("message.sw.unassigned", unAssignedSw.getName())); } - + } private static boolean isSoftModAvaiableForSoftType(final Set swModulesSet, From 9bd47a5c555956265f0a0ffa13ac2e8c3930759a Mon Sep 17 00:00:00 2001 From: Gaurav Date: Fri, 5 Aug 2016 10:49:24 +0200 Subject: [PATCH 16/22] Added the message in the message.properties. Signed-off-by: Gaurav --- .../detailslayout/SoftwareModuleDetailsTable.java | 4 +--- .../ui/distributions/dstable/DistributionSetTable.java | 10 ++++------ hawkbit-ui/src/main/resources/messages.properties | 1 + hawkbit-ui/src/main/resources/messages_de.properties | 1 + hawkbit-ui/src/main/resources/messages_en.properties | 1 + 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java index 036b229df..a7adb8711 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java @@ -187,9 +187,7 @@ public class SoftwareModuleDetailsTable extends Table { final Set alreadyAssignedSwModules) { final SoftwareModule unAssignedSw = getSoftwareModule(event.getButton().getId(), alreadyAssignedSwModules); if (distributionSetManagement.isDistributionSetInUse(distributionSet)) { - uiNotification.displayValidationError( - String.format("Distribution set %s:%s is already assigned to targets and cannot be changed", - distributionSet.getName(), distributionSet.getVersion())); + uiNotification.displayValidationError(i18n.get("message.error.notification.ds.target.assigned",distributionSet.getName(), distributionSet.getVersion())); } else { final DistributionSet newDistributionSet = distributionSetManagement.unassignSoftwareModule(distributionSet, unAssignedSw); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java index 1547ef11b..fc415f4de 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java @@ -334,9 +334,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable Date: Fri, 5 Aug 2016 13:04:56 +0200 Subject: [PATCH 17/22] refactor test using ClassPath from guava Signed-off-by: Michael Hirsch --- .../hawkbit-repository-api/pom.xml | 19 ++--- ...gementMethodPreAuthorizeAnnotatedTest.java | 81 ++----------------- 2 files changed, 14 insertions(+), 86 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/pom.xml b/hawkbit-repository/hawkbit-repository-api/pom.xml index 0a3f541d9..ce9b47a3d 100644 --- a/hawkbit-repository/hawkbit-repository-api/pom.xml +++ b/hawkbit-repository/hawkbit-repository-api/pom.xml @@ -1,13 +1,5 @@ - + 4.0.0 @@ -40,7 +32,7 @@ org.springframework.hateoas spring-hateoas - + org.springframework.boot @@ -64,5 +56,10 @@ fest-assert test + + com.google.guava + guava + test + \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java index a827b36e7..1a0d85d30 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java @@ -10,24 +10,21 @@ package org.eclipse.hawkbit.repository; import static org.fest.assertions.Assertions.assertThat; -import java.io.File; -import java.io.FileFilter; import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.junit.Test; import org.springframework.security.access.prepost.PreAuthorize; +import com.google.common.reflect.ClassPath; + import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Stories; @@ -83,38 +80,11 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { } } - /** - * Finds all interfaces in a given packages which matches the given filter. - * - * @param p - * the package to search for interfaces in - * @param includeFilter - * the pattern which interfaces class names should be included - * @return a list of loaded interfaces in a specific package and matches the - * given filter - * @throws URISyntaxException - * @throws IOException - * @throws ClassNotFoundException - */ private List> findInterfacesInPackage(final Package p, final Pattern includeFilter) throws URISyntaxException, IOException, ClassNotFoundException { - final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - final Enumeration resources = classLoader.getResources(p.getName().replace(".", "/")); - final RegexIncludeInterfaceFileCollector regexIncludeInterfaceFileCollector = new RegexIncludeInterfaceFileCollector( - p, includeFilter); - while (resources.hasMoreElements()) { - listFilesInPackage(resources.nextElement(), regexIncludeInterfaceFileCollector); - } - return regexIncludeInterfaceFileCollector.getInterfaceClasses(); - } - - private void listFilesInPackage(final URL resource, final RegexIncludeInterfaceFileCollector clazzCollector) - throws URISyntaxException { - final String packagePath = new URI(resource.toString()).getPath(); - if (packagePath != null) { - final File packageDirectory = new File(packagePath); - packageDirectory.listFiles(clazzCollector); - } + return ClassPath.from(Thread.currentThread().getContextClassLoader()).getTopLevelClasses(p.getName()).stream() + .filter(clazzInfo -> includeFilter.matcher(clazzInfo.getSimpleName()).matches()) + .map(clazzInfo -> clazzInfo.load()).filter(clazz -> clazz.isInterface()).collect(Collectors.toList()); } private static Method getMethod(final Class clazz, final String methodName, final Class... parameterTypes) { @@ -124,43 +94,4 @@ public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { throw new RuntimeException(e.getMessage(), e); } } - - private static final class RegexIncludeInterfaceFileCollector implements FileFilter { - - private final List> interfaceClasses = new ArrayList<>(); - private final Pattern includeFilter; - private final Package basePackage; - - public RegexIncludeInterfaceFileCollector(final Package basePackage, final Pattern pattern) { - this.basePackage = basePackage; - this.includeFilter = pattern; - } - - @Override - public boolean accept(final File pathname) { - final String classNameWithExtension = pathname.getName(); - final int indexOfExtension = classNameWithExtension.indexOf(".class"); - if (indexOfExtension == -1) { - return false; - } - final String classNameWithoutExtension = classNameWithExtension.substring(0, indexOfExtension); - if (!includeFilter.matcher(classNameWithoutExtension).matches()) { - return false; - } - - try { - final Class classInPackage = Class.forName(basePackage.getName() + "." + classNameWithoutExtension); - if (classInPackage.isInterface()) { - interfaceClasses.add(classInPackage); - } - } catch (final ClassNotFoundException e) { - // don't need to handle here - } - return false; - } - - public List> getInterfaceClasses() { - return interfaceClasses; - } - } } From cf0ed6d82845715e36f3fc1147e7fdb25e621007 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Fri, 5 Aug 2016 13:09:24 +0200 Subject: [PATCH 18/22] remove guava from test dependencies Signed-off-by: Michael Hirsch --- hawkbit-repository/hawkbit-repository-api/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/pom.xml b/hawkbit-repository/hawkbit-repository-api/pom.xml index ce9b47a3d..ccccaf038 100644 --- a/hawkbit-repository/hawkbit-repository-api/pom.xml +++ b/hawkbit-repository/hawkbit-repository-api/pom.xml @@ -56,10 +56,5 @@ fest-assert test - - com.google.guava - guava - test - \ No newline at end of file From 1e00439f3c29f1a48994f768f59399d33c4989d8 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Fri, 5 Aug 2016 13:13:46 +0200 Subject: [PATCH 19/22] add new line Signed-off-by: Michael Hirsch --- .../java/org/eclipse/hawkbit/repository/SystemManagement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java index e30009258..cd414b09a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java @@ -93,4 +93,4 @@ public interface SystemManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) TenantMetaData updateTenantMetadata(@NotNull TenantMetaData metaData); -} \ No newline at end of file +} From 431143133b833764b61dcc1dd79078dc9222e2ae Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Fri, 5 Aug 2016 13:19:29 +0200 Subject: [PATCH 20/22] fix license header Signed-off-by: Michael Hirsch --- hawkbit-repository/hawkbit-repository-api/pom.xml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hawkbit-repository/hawkbit-repository-api/pom.xml b/hawkbit-repository/hawkbit-repository-api/pom.xml index ccccaf038..e809ce29d 100644 --- a/hawkbit-repository/hawkbit-repository-api/pom.xml +++ b/hawkbit-repository/hawkbit-repository-api/pom.xml @@ -1,5 +1,13 @@ - + 4.0.0 From 88c1253f6691da391aa3870529a6f531e08d8bfd Mon Sep 17 00:00:00 2001 From: Gaurav Date: Fri, 5 Aug 2016 16:02:20 +0200 Subject: [PATCH 21/22] Fix for the concurrency issue on UI causes on the Nullpointer Exception. Signed-off-by: Gaurav --- .../ui/common/tagdetails/AbstractTagToken.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java index 9d36e3de0..5894e986c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java @@ -12,6 +12,7 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @@ -54,7 +55,7 @@ public abstract class AbstractTagToken implements Serializ protected IndexedContainer container; - protected final transient Map tagDetails = new HashMap<>(); + protected final transient Map tagDetails = new ConcurrentHashMap<>(); protected final transient Map tokensAdded = new HashMap<>(); @@ -140,10 +141,12 @@ public abstract class AbstractTagToken implements Serializ } protected void setContainerPropertValues(final Long tagId, final String tagName, final String tagColor) { - tagDetails.put(tagId, new TagData(tagId, tagName, tagColor)); - final Item item = container.addItem(tagId); - item.getItemProperty("id").setValue(tagId); - updateItem(tagName, tagColor, item); + final TagData tagData = tagDetails.putIfAbsent(tagId, new TagData(tagId, tagName, tagColor)); + if(tagData == null){ + final Item item = container.addItem(tagId); + item.getItemProperty("id").setValue(tagId); + updateItem(tagName, tagColor, item); + } } protected void updateItem(final String tagName, final String tagColor, final Item item) { From adafaa9489aaff7ff76b8909dbe2e9de57e5e368 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Mon, 8 Aug 2016 16:15:15 +0200 Subject: [PATCH 22/22] clear the tagDetails map as well Signed-off-by: Michael Hirsch --- .../eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java | 2 +- .../hawkbit/ui/common/tagdetails/DistributionTagToken.java | 1 + .../eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java index 5894e986c..2df040c65 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java @@ -142,7 +142,7 @@ public abstract class AbstractTagToken implements Serializ protected void setContainerPropertValues(final Long tagId, final String tagName, final String tagColor) { final TagData tagData = tagDetails.putIfAbsent(tagId, new TagData(tagId, tagName, tagColor)); - if(tagData == null){ + if (tagData == null) { final Item item = container.addItem(tagId); item.getItemProperty("id").setValue(tagId); updateItem(tagName, tagColor, item); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java index 88467d838..273dd3bf3 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java @@ -121,6 +121,7 @@ public class DistributionTagToken extends AbstractTagToken { @Override protected void populateContainer() { container.removeAllItems(); + tagDetails.clear(); for (final DistributionSetTag tag : tagManagement.findAllDistributionSetTags()) { setContainerPropertValues(tag.getId(), tag.getName(), tag.getColour()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java index 2cd4ec978..bd91302cf 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java @@ -120,6 +120,7 @@ public class TargetTagToken extends AbstractTargetTagToken { @Override protected void populateContainer() { container.removeAllItems(); + tagDetails.clear(); for (final TargetTag tag : tagManagement.findAllTargetTags()) { setContainerPropertValues(tag.getId(), tag.getName(), tag.getColour()); }