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:
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -39,7 +39,7 @@ public class HttpControllerPreAuthenticateAnonymousDownloadFilter extends Abstra
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreAuthentificationFilter createControllerAuthenticationFilter() {
|
||||
protected PreAuthenticationFilter createControllerAuthenticationFilter() {
|
||||
return new ControllerPreAuthenticatedAnonymousDownload(tenantConfigurationManagement, tenantAware,
|
||||
systemSecurityContext);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class HttpControllerPreAuthenticateSecurityTokenFilter extends AbstractHt
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreAuthentificationFilter createControllerAuthenticationFilter() {
|
||||
protected PreAuthenticationFilter createControllerAuthenticationFilter() {
|
||||
return new ControllerPreAuthenticateSecurityTokenFilter(tenantConfigurationManagement, controllerManagement,
|
||||
tenantAware, systemSecurityContext);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class HttpControllerPreAuthenticatedSecurityHeaderFilter extends Abstract
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreAuthentificationFilter createControllerAuthenticationFilter() {
|
||||
protected PreAuthenticationFilter createControllerAuthenticationFilter() {
|
||||
return new ControllerPreAuthenticatedSecurityHeaderFilter(caCommonNameHeader, caAuthorityNameHeader,
|
||||
tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user