Anonymous download activated does not result in general DDI anonymous (#616)

* Fix unintended anonymous access in DDI API.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix test.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix ant matcher.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2017-12-19 17:53:17 +01:00
committed by GitHub
parent 7d0bf3a162
commit 5d774dc70a
17 changed files with 199 additions and 93 deletions

View File

@@ -22,6 +22,7 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.eclipse.hawkbit.cache.DownloadIdCache;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
import org.eclipse.hawkbit.ddi.rest.resource.DdiApiConfiguration;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
@@ -134,32 +135,39 @@ public class SecurityManagedConfiguration {
}
/**
* {@link WebSecurityConfigurer} for the internal SP controller API.
* {@link WebSecurityConfigurer} for the hawkBit server DDI interface.
*/
@Configuration
@Order(300)
@ConditionalOnClass(DdiApiConfiguration.class)
static class ControllerSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private static final String DDI_ANT_MATCHER = "/{tenant}/controller/**";
private static final String[] DDI_ANT_MATCHERS = { DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}",
DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/deploymentBase/**",
DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/cancelAction/**",
DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/configData",
DdiRestConstants.BASE_V1_REQUEST_MAPPING
+ "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts" };
private final ControllerManagement controllerManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
private final TenantAware tenantAware;
private final DdiSecurityProperties ddiSecurityConfiguration;
private final SecurityProperties springSecurityProperties;
private final SystemSecurityContext systemSecurityContext;
@Autowired
private ControllerManagement controllerManagement;
@Autowired
private TenantConfigurationManagement tenantConfigurationManagement;
@Autowired
private TenantAware tenantAware;
@Autowired
private DdiSecurityProperties ddiSecurityConfiguration;
@Autowired
private SecurityProperties springSecurityProperties;
@Autowired
private SystemSecurityContext systemSecurityContext;
ControllerSecurityConfigurationAdapter(final ControllerManagement controllerManagement,
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
final DdiSecurityProperties ddiSecurityConfiguration, final SecurityProperties springSecurityProperties,
final SystemSecurityContext systemSecurityContext) {
this.controllerManagement = controllerManagement;
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.tenantAware = tenantAware;
this.ddiSecurityConfiguration = ddiSecurityConfiguration;
this.springSecurityProperties = springSecurityProperties;
this.systemSecurityContext = systemSecurityContext;
}
/**
* Filter to protect the hawkBit server DDI interface against to many
@@ -175,7 +183,7 @@ public class SecurityManagedConfiguration {
@ConditionalOnProperty(prefix = "hawkbit.server.security.dos.filter", name = "enabled", matchIfMissing = true)
public FilterRegistrationBean dosDDiFilter(final HawkbitSecurityProperties securityProperties) {
final FilterRegistrationBean filterRegBean = dosFilter(Arrays.asList(DDI_ANT_MATCHER),
final FilterRegistrationBean filterRegBean = dosFilter(Arrays.asList(DDI_ANT_MATCHERS),
securityProperties.getDos().getFilter(), securityProperties.getClients());
filterRegBean.setOrder(DOS_FILTER_ORDER);
filterRegBean.setName("dosDDiFilter");
@@ -183,6 +191,122 @@ public class SecurityManagedConfiguration {
return filterRegBean;
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
final ControllerTenantAwareAuthenticationDetailsSource authenticationDetailsSource = new ControllerTenantAwareAuthenticationDetailsSource();
final HttpControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new HttpControllerPreAuthenticatedSecurityHeaderFilter(
ddiSecurityConfiguration.getRp().getCnHeader(),
ddiSecurityConfiguration.getRp().getSslIssuerHashHeader(), tenantConfigurationManagement,
tenantAware, systemSecurityContext);
securityHeaderFilter.setAuthenticationManager(authenticationManager());
securityHeaderFilter.setCheckForPrincipalChanges(true);
securityHeaderFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
final HttpControllerPreAuthenticateSecurityTokenFilter securityTokenFilter = new HttpControllerPreAuthenticateSecurityTokenFilter(
tenantConfigurationManagement, tenantAware, controllerManagement, systemSecurityContext);
securityTokenFilter.setAuthenticationManager(authenticationManager());
securityTokenFilter.setCheckForPrincipalChanges(true);
securityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
final HttpControllerPreAuthenticatedGatewaySecurityTokenFilter gatewaySecurityTokenFilter = new HttpControllerPreAuthenticatedGatewaySecurityTokenFilter(
tenantConfigurationManagement, tenantAware, systemSecurityContext);
gatewaySecurityTokenFilter.setAuthenticationManager(authenticationManager());
gatewaySecurityTokenFilter.setCheckForPrincipalChanges(true);
gatewaySecurityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
HttpSecurity httpSec = http.csrf().disable();
if (springSecurityProperties.isRequireSsl()) {
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
}
if (ddiSecurityConfiguration.getAuthentication().getAnonymous().isEnabled()) {
LOG.info(
"******************\n** Anonymous controller security enabled, should only be used for developing purposes **\n******************");
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
"controllerAnonymousFilter", "anonymous",
Arrays.asList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
anoymousFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
httpSec.requestMatchers().antMatchers(DDI_ANT_MATCHERS).and().securityContext().disable().anonymous()
.authenticationFilter(anoymousFilter);
} else {
httpSec.addFilter(securityHeaderFilter).addFilter(securityTokenFilter)
.addFilter(gatewaySecurityTokenFilter).requestMatchers().antMatchers(DDI_ANT_MATCHERS).and()
.anonymous().disable().authorizeRequests().anyRequest().authenticated().and()
.exceptionHandling()
.authenticationEntryPoint((request, response, authException) -> response
.setStatus(HttpStatus.UNAUTHORIZED.value()))
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new PreAuthTokenSourceTrustAuthenticationProvider(
ddiSecurityConfiguration.getRp().getTrustedIPs()));
}
}
/**
* {@link WebSecurityConfigurer} for the hawkBit server DDI download
* interface.
*/
@Configuration
@Order(301)
@ConditionalOnClass(DdiApiConfiguration.class)
static class ControllerDownloadSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private static final String DDI_DL_ANT_MATCHER = DdiRestConstants.BASE_V1_REQUEST_MAPPING
+ "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/*";
private final ControllerManagement controllerManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
private final TenantAware tenantAware;
private final DdiSecurityProperties ddiSecurityConfiguration;
private final SecurityProperties springSecurityProperties;
private final SystemSecurityContext systemSecurityContext;
@Autowired
ControllerDownloadSecurityConfigurationAdapter(final ControllerManagement controllerManagement,
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
final DdiSecurityProperties ddiSecurityConfiguration, final SecurityProperties springSecurityProperties,
final SystemSecurityContext systemSecurityContext) {
this.controllerManagement = controllerManagement;
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.tenantAware = tenantAware;
this.ddiSecurityConfiguration = ddiSecurityConfiguration;
this.springSecurityProperties = springSecurityProperties;
this.systemSecurityContext = systemSecurityContext;
}
/**
* Filter to protect the hawkBit server DDI download interface against
* to many requests.
*
* @param securityProperties
* for filter configuration
*
* @return the spring filter registration bean for registering a denial
* of service protection filter in the filter chain
*/
@Bean
@ConditionalOnProperty(prefix = "hawkbit.server.security.dos.filter", name = "enabled", matchIfMissing = true)
public FilterRegistrationBean dosDDiDlFilter(final HawkbitSecurityProperties securityProperties) {
final FilterRegistrationBean filterRegBean = dosFilter(Arrays.asList(DDI_DL_ANT_MATCHER),
securityProperties.getDos().getFilter(), securityProperties.getClients());
filterRegBean.setOrder(DOS_FILTER_ORDER);
filterRegBean.setName("dosDDiDlFilter");
return filterRegBean;
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
@@ -227,17 +351,16 @@ public class SecurityManagedConfiguration {
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
"controllerAnonymousFilter", "anonymous",
Arrays.asList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS),
new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE)));
Arrays.asList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
anoymousFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
httpSec.requestMatchers().antMatchers(DDI_ANT_MATCHER).and().securityContext().disable().anonymous()
httpSec.requestMatchers().antMatchers(DDI_DL_ANT_MATCHER).and().securityContext().disable().anonymous()
.authenticationFilter(anoymousFilter);
} else {
httpSec.addFilter(securityHeaderFilter).addFilter(securityTokenFilter)
.addFilter(gatewaySecurityTokenFilter).addFilter(controllerAnonymousDownloadFilter)
.antMatcher(DDI_ANT_MATCHER).anonymous().disable().authorizeRequests().anyRequest()
.authenticated().and().exceptionHandling()
.requestMatchers().antMatchers(DDI_DL_ANT_MATCHER).and().anonymous().disable()
.authorizeRequests().anyRequest().authenticated().and().exceptionHandling()
.authenticationEntryPoint((request, response, authException) -> response
.setStatus(HttpStatus.UNAUTHORIZED.value()))
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

View File

@@ -22,10 +22,10 @@ import org.eclipse.hawkbit.security.ControllerPreAuthenticatedAnonymousFilter;
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedGatewaySecurityTokenFilter;
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedSecurityHeaderFilter;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.DmfTenantSecurityToken;
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
import org.eclipse.hawkbit.security.PreAuthentificationFilter;
import org.eclipse.hawkbit.security.PreAuthenticationFilter;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.security.DmfTenantSecurityToken;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,7 +44,7 @@ public class AmqpControllerAuthentication {
private final PreAuthTokenSourceTrustAuthenticationProvider preAuthenticatedAuthenticationProvider = new PreAuthTokenSourceTrustAuthenticationProvider();
private List<PreAuthentificationFilter> filterChain;
private List<PreAuthenticationFilter> filterChain;
private final ControllerManagement controllerManagement;
@@ -124,7 +124,7 @@ public class AmqpControllerAuthentication {
public Authentication doAuthenticate(final DmfTenantSecurityToken securityToken) {
resolveTenant(securityToken);
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(null, null);
for (final PreAuthentificationFilter filter : filterChain) {
for (final PreAuthenticationFilter filter : filterChain) {
final PreAuthenticatedAuthenticationToken authenticationRest = createAuthentication(filter, securityToken);
if (authenticationRest != null) {
authentication = authenticationRest;
@@ -144,7 +144,7 @@ public class AmqpControllerAuthentication {
}
private static PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthentificationFilter filter,
private static PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthenticationFilter filter,
final DmfTenantSecurityToken secruityToken) {
if (!filter.isEnable(secruityToken)) {
@@ -161,7 +161,8 @@ public class AmqpControllerAuthentication {
LOGGER.debug("preAuthenticatedPrincipal = {} trying to authenticate", principal);
return new PreAuthenticatedAuthenticationToken(principal, credentials);
return new PreAuthenticatedAuthenticationToken(principal, credentials,
filter.getSuccessfulAuthenticationAuthorities());
}
}

View File

@@ -92,7 +92,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Target in the message is null.This message is invalid and should not requeued. Additional the receive message is null")
public void securityTokenFileResourceIsNull() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET, null);
final Message returnMessage = sendAndReceiveAuthenticationMessage(securityToken);
verifyResult(returnMessage, HttpStatus.NOT_FOUND, null);
@@ -114,7 +114,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Verify that the receive message contains a 404 code,if the artifact could not found")
public void fileResourceGetSha1InSecurityTokenIsNull() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
FileResource.createFileResourceBySha1(null));
@@ -143,7 +143,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Verify that the receive message contains a 404 code, if there is no artifact for the given sha1")
public void artifactForFileResourceSHA1NotFound() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
FileResource.createFileResourceBySha1(TARGET_SECRUITY_TOKEN));
@@ -156,7 +156,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Verify that the receive message contains a 404 code, if there is no existing target for the given controller id")
public void artifactForFileResourceSHA1FoundTargetNotExists() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DistributionSet distributionSet = createDistributionSet();
final List<Artifact> artifacts = createArtifacts(distributionSet);
final String sha1Hash = artifacts.get(0).getSha1Hash();
@@ -226,7 +226,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Verify that the receive message contains a 200 code and a artifact without a controller id (anonymous enabled)")
public void anonymousAuthentification() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DistributionSet distributionSet = createDistributionSet();
final List<Artifact> artifacts = createArtifacts(distributionSet);
final Artifact artifact = artifacts.get(0);
@@ -260,7 +260,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Verify that the receive message contains a 404, if there is no artifact to the given filename")
public void artifactForFileResourceFileNameNotFound() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
FileResource.createFileResourceByFilename("Test.txt"));
@@ -289,7 +289,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Verify that the receive message contains a 404, if there is no exisiting target")
public void artifactForFileResourceArtifactIdFoundTargetNotExists() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DistributionSet distributionSet = createDistributionSet();
final List<Artifact> artifacts = createArtifacts(distributionSet);
final FileResource fileResource = FileResource.createFileResourceByArtifactId(artifacts.get(0).getId());
@@ -323,7 +323,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Verify that the receive message contains a 404, if there is no artifact to the given softwareModuleFilename")
public void artifactForFileResourceSoftwareModuleFilenameNotFound() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DmfTenantSecurityToken securityToken = createTenantSecurityToken(TENANT_EXIST, TARGET,
FileResource.softwareModuleFilename(1L, "Test.txt"));
@@ -336,7 +336,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
@Test
@Description("Verify that the receive message contains a 404, if there is no existing target for the file resource")
public void artifactForFileResourceSoftwareModuleFilenameFoundTargetNotExists() {
enableAnonymousAuthentification();
enableAnonymousAuthentication();
final DistributionSet distributionSet = createDistributionSet();
final List<Artifact> artifacts = createArtifacts(distributionSet);
@@ -376,7 +376,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
}
private void verifyOkResult(Message returnMessage, Artifact artifact) {
private void verifyOkResult(final Message returnMessage, final Artifact artifact) {
final DmfDownloadResponse convertedMessage = verifyResult(returnMessage, HttpStatus.OK, null);
assertThat(convertedMessage.getDownloadUrl()).isNotNull();
assertThat(convertedMessage.getArtifact()).isNotNull();
@@ -384,7 +384,7 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
}
private void enableAnonymousAuthentification() {
private void enableAnonymousAuthentication() {
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED,
true);
tenantConfigurationManagement.addOrUpdateConfiguration(
@@ -405,15 +405,16 @@ public class AmqpAuthenticationMessageHandlerIntegrationTest extends AbstractAmq
private DmfTenantSecurityToken createTenantSecurityToken(final String tenant, final String controllerId,
final FileResource fileResource) {
final DmfTenantSecurityToken tenantSecurityToken = new DmfTenantSecurityToken(tenant, controllerId, fileResource);
final DmfTenantSecurityToken tenantSecurityToken = new DmfTenantSecurityToken(tenant, controllerId,
fileResource);
tenantSecurityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, TARGET_TOKEN_HEADER);
return tenantSecurityToken;
}
private DmfTenantSecurityToken createTenantSecurityToken(final String tenant, final Long targetId,
final String controllerId, final FileResource fileResource) {
final DmfTenantSecurityToken tenantSecurityToken = new DmfTenantSecurityToken(tenant, null, controllerId, targetId,
fileResource);
final DmfTenantSecurityToken tenantSecurityToken = new DmfTenantSecurityToken(tenant, null, controllerId,
targetId, fileResource);
tenantSecurityToken.putHeader(DmfTenantSecurityToken.AUTHORIZATION_HEADER, TARGET_TOKEN_HEADER);
return tenantSecurityToken;
}

View File

@@ -65,7 +65,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
private final AntPathMatcher pathExtractor;
private PreAuthentificationFilter abstractControllerAuthenticationFilter;
private PreAuthenticationFilter abstractControllerAuthenticationFilter;
/**
* Constructor for sub-classes.
@@ -108,7 +108,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
}
}
protected abstract PreAuthentificationFilter createControllerAuthenticationFilter();
protected abstract PreAuthenticationFilter createControllerAuthenticationFilter();
@Override
protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response,

View File

@@ -39,7 +39,7 @@ public class HttpControllerPreAuthenticateAnonymousDownloadFilter extends Abstra
}
@Override
protected PreAuthentificationFilter createControllerAuthenticationFilter() {
protected PreAuthenticationFilter createControllerAuthenticationFilter() {
return new ControllerPreAuthenticatedAnonymousDownload(tenantConfigurationManagement, tenantAware,
systemSecurityContext);
}

View File

@@ -55,7 +55,7 @@ public class HttpControllerPreAuthenticateSecurityTokenFilter extends AbstractHt
}
@Override
protected PreAuthentificationFilter createControllerAuthenticationFilter() {
protected PreAuthenticationFilter createControllerAuthenticationFilter() {
return new ControllerPreAuthenticateSecurityTokenFilter(tenantConfigurationManagement, controllerManagement,
tenantAware, systemSecurityContext);
}

View File

@@ -34,7 +34,7 @@ public class HttpControllerPreAuthenticatedGatewaySecurityTokenFilter
* the tenant aware service to get configuration for the specific
* tenant
* @param systemSecurityContext
* * @param systemSecurityContext the system security context
* the system security context
*/
public HttpControllerPreAuthenticatedGatewaySecurityTokenFilter(
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
@@ -43,7 +43,7 @@ public class HttpControllerPreAuthenticatedGatewaySecurityTokenFilter
}
@Override
protected PreAuthentificationFilter createControllerAuthenticationFilter() {
protected PreAuthenticationFilter createControllerAuthenticationFilter() {
return new ControllerPreAuthenticatedGatewaySecurityTokenFilter(tenantConfigurationManagement, tenantAware,
systemSecurityContext);
}

View File

@@ -54,7 +54,7 @@ public class HttpControllerPreAuthenticatedSecurityHeaderFilter extends Abstract
}
@Override
protected PreAuthentificationFilter createControllerAuthenticationFilter() {
protected PreAuthenticationFilter createControllerAuthenticationFilter() {
return new ControllerPreAuthenticatedSecurityHeaderFilter(caCommonNameHeader, caAuthorityNameHeader,
tenantConfigurationManagement, tenantAware, systemSecurityContext);
}

View File

@@ -204,7 +204,7 @@ public interface ArtifactManagement {
*
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DOWNLOAD_ARTIFACT + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_CONTROLLER_DOWNLOAD)
+ SpringEvalExpressions.IS_CONTROLLER)
Optional<AbstractDbArtifact> loadArtifactBinary(@NotEmpty String sha1Hash);
}

View File

@@ -12,7 +12,7 @@ security.user.name=admin
security.user.password=admin
# DDI authentication configuration
hawkbit.server.ddi.security.authentication.anonymous.enabled=true
hawkbit.server.ddi.security.authentication.anonymous.enabled=false
hawkbit.server.ddi.security.authentication.targettoken.enabled=true
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=true

View File

@@ -246,12 +246,6 @@ public final class SpPermission {
*/
public static final String CONTROLLER_ROLE_ANONYMOUS = "ROLE_CONTROLLER_ANONYMOUS";
/**
* The role which contains in the spring security context in case an
* controller is authenticated to download artifacts.
*/
public static final String CONTROLLER_DOWNLOAD_ROLE = "ROLE_CONTROLLER_DOWNLOAD";
/**
* The role which contains the spring security context in case the
* system is executing code which is necessary to be privileged.
@@ -384,14 +378,6 @@ public final class SpPermission {
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
+ "')";
/**
* Spring security eval hasAuthority expression to check if the spring
* context contains the role to allow controllers to download specific
* role {@link SpringEvalExpressions#CONTROLLER_DOWNLOAD_ROLE}
*/
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
+ HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} and

View File

@@ -8,19 +8,22 @@
*/
package org.eclipse.hawkbit.security;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
/**
* An abstraction for all controller based security. Check if the tenant
* configuration is enabled.
*
*
*
*/
public abstract class AbstractControllerAuthenticationFilter implements PreAuthentificationFilter {
public abstract class AbstractControllerAuthenticationFilter implements PreAuthenticationFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractControllerAuthenticationFilter.class);
@@ -54,4 +57,9 @@ public abstract class AbstractControllerAuthenticationFilter implements PreAuthe
}
}
@Override
public Collection<GrantedAuthority> getSuccessfulAuthenticationAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE));
}
}

View File

@@ -8,15 +8,10 @@
*/
package org.eclipse.hawkbit.security;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
/**
* An pre-authenticated processing filter which add the
@@ -59,9 +54,4 @@ public class ControllerPreAuthenticatedAnonymousDownload extends AbstractControl
protected String getTenantConfigurationKey() {
return TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED;
}
@Override
public Collection<GrantedAuthority> getSuccessfulAuthenticationAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE));
}
}

View File

@@ -14,7 +14,7 @@ package org.eclipse.hawkbit.security;
*
* @see DdiSecurityProperties
*/
public class ControllerPreAuthenticatedAnonymousFilter implements PreAuthentificationFilter {
public class ControllerPreAuthenticatedAnonymousFilter implements PreAuthenticationFilter {
private final DdiSecurityProperties ddiSecurityConfiguration;

View File

@@ -12,7 +12,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
@@ -20,7 +19,6 @@ import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
/**
@@ -91,19 +89,17 @@ public class PreAuthTokenSourceTrustAuthenticationProvider implements Authentica
final Object credentials = token.getCredentials();
final Object principal = token.getPrincipal();
final Object tokenDetails = token.getDetails();
final Collection<GrantedAuthority> authorities = token.getAuthorities();
if (principal == null) {
throw new BadCredentialsException("The provided principal and credentials are not match");
}
boolean successAuthentication = calculateAuthenticationSuccess(principal, credentials, tokenDetails);
final boolean successAuthentication = calculateAuthenticationSuccess(principal, credentials, tokenDetails);
if (successAuthentication) {
final Collection<GrantedAuthority> controllerAuthorities = new ArrayList<>();
controllerAuthorities.add(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE));
controllerAuthorities.add(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE));
final PreAuthenticatedAuthenticationToken successToken = new PreAuthenticatedAuthenticationToken(principal,
credentials, controllerAuthorities);
credentials, authorities);
successToken.setDetails(tokenDetails);
return successToken;
}
@@ -132,7 +128,8 @@ public class PreAuthTokenSourceTrustAuthenticationProvider implements Authentica
* @return <code>true</code> if authentication succeeded, otherwise
* <code>false</code>
*/
private boolean calculateAuthenticationSuccess(Object principal, Object credentials, Object tokenDetails) {
private boolean calculateAuthenticationSuccess(final Object principal, final Object credentials,
final Object tokenDetails) {
boolean successAuthentication = false;
if (credentials instanceof Collection) {
final Collection<?> multiValueCredentials = (Collection<?>) credentials;

View File

@@ -15,9 +15,9 @@ import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
/**
* Interface for Pre Authentification.
* Interface for Pre Authentication.
*/
public interface PreAuthentificationFilter {
public interface PreAuthenticationFilter {
/**
* Check if the filter is enabled.

View File

@@ -56,6 +56,6 @@ public class ControllerPreAuthenticatedAnonymousDownloadTest {
public void successfulAuthenticationAdditionalAuthoritiesForDownload() {
assertThat(underTest.getSuccessfulAuthenticationAuthorities())
.as("Additional authorities should be containing the download anonymous role")
.contains(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE));
.contains(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE));
}
}