add security and filters for anonymous download via http and amqp
requests Signed-off-by: Michael Hirsch <michael.hirsch@bosch-si.com>
This commit is contained in:
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.autoconfigure.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.servlet.Filter;
|
||||
@@ -35,6 +34,7 @@ import org.eclipse.hawkbit.security.ControllerTenantAwareAuthenticationDetailsSo
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DosFilter;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateAnonymousDownloadFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedSecurityHeaderFilter;
|
||||
@@ -83,6 +83,8 @@ import org.vaadin.spring.security.web.VaadinRedirectStrategy;
|
||||
import org.vaadin.spring.security.web.authentication.VaadinAuthenticationSuccessHandler;
|
||||
import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSuccessHandler;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* All configurations related to SP authentication and authorization layer.
|
||||
*
|
||||
@@ -147,6 +149,12 @@ public class SecurityManagedConfiguration {
|
||||
gatewaySecurityTokenFilter.setCheckForPrincipalChanges(true);
|
||||
gatewaySecurityTokenFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
|
||||
final HttpControllerPreAuthenticateAnonymousDownloadFilter controllerAnonymousDownloadFilter = new HttpControllerPreAuthenticateAnonymousDownloadFilter(
|
||||
tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||
controllerAnonymousDownloadFilter.setAuthenticationManager(authenticationManager());
|
||||
controllerAnonymousDownloadFilter.setCheckForPrincipalChanges(true);
|
||||
controllerAnonymousDownloadFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
|
||||
HttpSecurity httpSec = http.csrf().disable().headers()
|
||||
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY)).contentTypeOptions()
|
||||
.xssProtection().httpStrictTransportSecurity().and();
|
||||
@@ -159,15 +167,17 @@ public class SecurityManagedConfiguration {
|
||||
LOG.info(
|
||||
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
|
||||
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
|
||||
"controllerAnonymousFilter", "anonymous", Collections.singletonList(
|
||||
new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
|
||||
"controllerAnonymousFilter", "anonymous",
|
||||
Lists.newArrayList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS),
|
||||
new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE)));
|
||||
anoymousFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
httpSec.requestMatchers().antMatchers("/*/controller/v1/**", "/*/controller/artifacts/v1/**").and()
|
||||
.securityContext().disable().anonymous().authenticationFilter(anoymousFilter);
|
||||
} else {
|
||||
httpSec.addFilter(securityHeaderFilter).addFilter(securityTokenFilter)
|
||||
.addFilter(gatewaySecurityTokenFilter).antMatcher("/*/controller/**").anonymous().disable()
|
||||
.authorizeRequests().anyRequest().authenticated().and().exceptionHandling()
|
||||
.addFilter(gatewaySecurityTokenFilter).addFilter(controllerAnonymousDownloadFilter)
|
||||
.antMatcher("/*/controller/**").anonymous().disable().authorizeRequests().anyRequest()
|
||||
.authenticated().and().exceptionHandling()
|
||||
.authenticationEntryPoint((request, response, authException) -> response
|
||||
.setStatus(HttpStatus.UNAUTHORIZED.value()))
|
||||
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
|
||||
@@ -19,6 +19,8 @@ import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.security.CoapAnonymousPreAuthenticatedFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticateSecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedAnonymousDownload;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedAnonymousFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedSecurityHeaderFilter;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
@@ -90,6 +92,11 @@ public class AmqpControllerAuthentfication {
|
||||
tenantConfigurationManagement, controllerManagement, tenantAware, systemSecurityContext);
|
||||
filterChain.add(securityTokenFilter);
|
||||
|
||||
final ControllerPreAuthenticatedAnonymousDownload anonymousDownloadFilter = new ControllerPreAuthenticatedAnonymousDownload(
|
||||
tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||
filterChain.add(anonymousDownloadFilter);
|
||||
|
||||
filterChain.add(new ControllerPreAuthenticatedAnonymousFilter(ddiSecruityProperties));
|
||||
filterChain.add(new CoapAnonymousPreAuthenticatedFilter());
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
||||
import org.eclipse.hawkbit.dmf.json.model.ArtifactHash;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
@@ -158,8 +158,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
private Message handleAuthentifiactionMessage(final Message message) {
|
||||
final DownloadResponse authentificationResponse = new DownloadResponse();
|
||||
final MessageProperties messageProperties = message.getMessageProperties();
|
||||
final TenantSecurityToken secruityToken = convertMessage(message,
|
||||
TenantSecurityToken.class);
|
||||
final TenantSecurityToken secruityToken = convertMessage(message, TenantSecurityToken.class);
|
||||
final FileResource fileResource = secruityToken.getFileResource();
|
||||
try {
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken));
|
||||
@@ -221,12 +220,11 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
} else if (fileResource.getFilename() != null) {
|
||||
localArtifact = artifactManagement.findLocalArtifactByFilename(fileResource.getFilename()).stream()
|
||||
.findFirst().orElse(null);
|
||||
} else if (fileResource.getArtifactId() != null) {
|
||||
final org.eclipse.hawkbit.repository.model.Artifact artifact = artifactManagement
|
||||
.findArtifact(fileResource.getArtifactId());
|
||||
if (artifact instanceof LocalArtifact) {
|
||||
localArtifact = (LocalArtifact) artifact;
|
||||
}
|
||||
} else if (fileResource.getSoftwareModuleFilenameResource() != null) {
|
||||
localArtifact = artifactManagement
|
||||
.findByFilenameAndSoftwareModule(fileResource.getSoftwareModuleFilenameResource().getFilename(),
|
||||
fileResource.getSoftwareModuleFilenameResource().getSoftwareModuleId())
|
||||
.stream().findFirst().orElse(null);
|
||||
}
|
||||
return localArtifact;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties.Authentication.Anonymous;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties.Rp;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
@@ -80,8 +81,14 @@ public class AmqpControllerAuthenticationTest {
|
||||
|
||||
final DdiSecurityProperties secruityProperties = mock(DdiSecurityProperties.class);
|
||||
final Rp rp = mock(Rp.class);
|
||||
final org.eclipse.hawkbit.security.DdiSecurityProperties.Authentication ddiAuthentication = mock(
|
||||
org.eclipse.hawkbit.security.DdiSecurityProperties.Authentication.class);
|
||||
final Anonymous anonymous = mock(Anonymous.class);
|
||||
when(secruityProperties.getRp()).thenReturn(rp);
|
||||
when(rp.getSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
|
||||
when(secruityProperties.getAuthentication()).thenReturn(ddiAuthentication);
|
||||
when(ddiAuthentication.getAnonymous()).thenReturn(anonymous);
|
||||
when(anonymous.isEnabled()).thenReturn(false);
|
||||
authenticationManager.setSecruityProperties(secruityProperties);
|
||||
|
||||
tenantConfigurationManagement = mock(TenantConfigurationManagement.class);
|
||||
|
||||
@@ -103,7 +103,7 @@ public class TenantSecurityToken {
|
||||
@JsonProperty(required = false)
|
||||
private String filename;
|
||||
@JsonProperty(required = false)
|
||||
private Long artifactId;
|
||||
private SoftwareModuleFilenameResource softwareModuleFilenameResource;
|
||||
|
||||
public String getSha1() {
|
||||
return sha1;
|
||||
@@ -121,12 +121,13 @@ public class TenantSecurityToken {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public Long getArtifactId() {
|
||||
return artifactId;
|
||||
public SoftwareModuleFilenameResource getSoftwareModuleFilenameResource() {
|
||||
return softwareModuleFilenameResource;
|
||||
}
|
||||
|
||||
public void setArtifactId(final Long artifactId) {
|
||||
this.artifactId = artifactId;
|
||||
public void setSoftwareModuleFilenameResource(
|
||||
final SoftwareModuleFilenameResource softwareModuleFilenameResource) {
|
||||
this.softwareModuleFilenameResource = softwareModuleFilenameResource;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,15 +157,19 @@ public class TenantSecurityToken {
|
||||
}
|
||||
|
||||
/**
|
||||
* factory method to create a file resource for an artifactId lookup.
|
||||
* factory method to create a file resource for an softwaremodule +
|
||||
* filename lookup, because an filename is not globally unique but
|
||||
* within a softwaremodule.
|
||||
*
|
||||
* @param artifactId
|
||||
* the artifactId of the file to obtain
|
||||
* @param softwareModuleId
|
||||
* the ID of the software module which contains the artifact
|
||||
* @param filename
|
||||
* the name of file to obtain within the software module
|
||||
* @return the {@link FileResource} with artifactId set
|
||||
*/
|
||||
public static FileResource artifactId(final Long artifactId) {
|
||||
public static FileResource softwareModuleFilename(final Long softwareModuleId, final String filename) {
|
||||
final FileResource resource = new FileResource();
|
||||
resource.artifactId = artifactId;
|
||||
resource.softwareModuleFilenameResource = new SoftwareModuleFilenameResource(softwareModuleId, filename);
|
||||
return resource;
|
||||
}
|
||||
|
||||
@@ -172,5 +177,42 @@ public class TenantSecurityToken {
|
||||
public String toString() {
|
||||
return "FileResource [sha1=" + sha1 + ", filename=" + filename + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class which holds the pointer to an artifact based on the
|
||||
* softwaremoduleId and the filename.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class SoftwareModuleFilenameResource {
|
||||
@JsonProperty(required = false)
|
||||
private final Long softwareModuleId;
|
||||
@JsonProperty(required = false)
|
||||
private final String filename;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param softwareModuleId
|
||||
* the ID of the softwaremodule
|
||||
* @param filename
|
||||
* the name of the file of the artifact within the
|
||||
* softwaremodule
|
||||
*/
|
||||
@JsonCreator
|
||||
public SoftwareModuleFilenameResource(@JsonProperty("softwareModuleId") final Long softwareModuleId,
|
||||
@JsonProperty("filename") final String filename) {
|
||||
this.softwareModuleId = softwareModuleId;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public Long getSoftwareModuleId() {
|
||||
return softwareModuleId;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
@@ -16,6 +18,7 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||
@@ -23,8 +26,11 @@ 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.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
@@ -80,14 +86,6 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
pathExtractor = new AntPathMatcher();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.security.web.authentication.preauth.
|
||||
* AbstractPreAuthenticatedProcessingFilter
|
||||
* #doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
|
||||
* javax.servlet.FilterChain)
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
@@ -113,6 +111,18 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
|
||||
protected abstract PreAuthenficationFilter createControllerAuthenticationFilter();
|
||||
|
||||
@Override
|
||||
protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response,
|
||||
final Authentication authResult) {
|
||||
final Collection<GrantedAuthority> authorities = new ArrayList<>();
|
||||
authorities.addAll(authResult.getAuthorities());
|
||||
authorities.addAll(abstractControllerAuthenticationFilter.getSuccessfulAuthenticationAuthorities());
|
||||
final PreAuthenticatedAuthenticationToken authTokenWithGrantedAuthorities = new PreAuthenticatedAuthenticationToken(
|
||||
authResult.getPrincipal(), authResult.getCredentials(), authorities);
|
||||
authTokenWithGrantedAuthorities.setDetails(authResult.getDetails());
|
||||
super.successfulAuthentication(request, response, authTokenWithGrantedAuthorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts tenant and controllerId from the request URI as path variables.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
|
||||
/**
|
||||
* An pre-authenticated processing filter which add the
|
||||
* {@link SpringEvalExpressions#CONTROLLER_DOWNLOAD_ROLE_ANONYMOUS} to the
|
||||
* security context in case the anonymous download is allowed through
|
||||
* configuration.
|
||||
*/
|
||||
public class HttpControllerPreAuthenticateAnonymousDownloadFilter extends AbstractHttpControllerAuthenticationFilter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenantConfigurationManagement
|
||||
* the system management service to retrieve configuration
|
||||
* properties
|
||||
* @param tenantAware
|
||||
* the tenant aware service to get configuration for the specific
|
||||
* tenant
|
||||
* @param systemSecurityContext
|
||||
* the system security context
|
||||
*/
|
||||
public HttpControllerPreAuthenticateAnonymousDownloadFilter(
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
|
||||
final SystemSecurityContext systemSecurityContext) {
|
||||
super(tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreAuthenficationFilter createControllerAuthenticationFilter() {
|
||||
return new ControllerPreAuthenticatedAnonymousDownload(tenantConfigurationManagement, tenantAware,
|
||||
systemSecurityContext);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -404,7 +404,7 @@ public class ArtifactManagement {
|
||||
* if file could not be found in store
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DOWNLOAD_ARTIFACT + SpringEvalExpressions.HAS_AUTH_OR
|
||||
+ SpringEvalExpressions.IS_CONTROLLER)
|
||||
+ SpringEvalExpressions.HAS_CONTROLLER_DOWNLOAD)
|
||||
public DbArtifact loadLocalArtifactBinary(@NotNull final LocalArtifact artifact) {
|
||||
final DbArtifact result = artifactRepository.getArtifactBySha1(artifact.getGridFsFileName());
|
||||
if (result == null) {
|
||||
|
||||
@@ -182,6 +182,12 @@ 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.
|
||||
@@ -275,8 +281,16 @@ public final class SpPermission {
|
||||
* context contains the anoynmous role or the controller specific role
|
||||
* {@link SpPermission#CONTROLLER_ROLE}.
|
||||
*/
|
||||
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '"
|
||||
+ CONTROLLER_ROLE + "')";
|
||||
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 SpPermission#CONTROLLER_DOWNLOAD_ROLE}.
|
||||
*/
|
||||
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
|
||||
+ HAS_AUTH_SUFFIX;
|
||||
|
||||
/**
|
||||
* Spring security eval hasAnyRole expression to check if the spring
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
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.TenantConfigurationKey;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* An pre-authenticated processing filter which add the
|
||||
* {@link SpringEvalExpressions#CONTROLLER_DOWNLOAD_ROLE_ANONYMOUS} to the
|
||||
* security context in case the anonymous download is allowed through
|
||||
* configuration.
|
||||
*/
|
||||
public class ControllerPreAuthenticatedAnonymousDownload extends AbstractControllerAuthenticationFilter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenantConfigurationManagement
|
||||
* the tenant management service to retrieve configuration
|
||||
* properties
|
||||
* @param tenantAware
|
||||
* the tenant aware service to get configuration for the specific
|
||||
* tenant
|
||||
* @param systemSecurityContext
|
||||
* the system security context to get access to tenant
|
||||
* configuration
|
||||
*/
|
||||
public ControllerPreAuthenticatedAnonymousDownload(
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
|
||||
final SystemSecurityContext systemSecurityContext) {
|
||||
super(tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), secruityToken.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), secruityToken.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TenantConfigurationKey getTenantConfigurationKey() {
|
||||
return TenantConfigurationKey.ANONYMOUS_DOWNLOAD_MODE_ENABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<GrantedAuthority> getSuccessfulAuthenticationAuthorities() {
|
||||
return Lists.newArrayList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
|
||||
/**
|
||||
* An anonymous controller filter which is only enabled in case of anonymous
|
||||
* access is granted. This should only be for development purposes.
|
||||
*
|
||||
* @see DdiSecurityProperties
|
||||
*/
|
||||
public class ControllerPreAuthenticatedAnonymousFilter implements PreAuthenficationFilter {
|
||||
|
||||
private final DdiSecurityProperties ddiSecurityConfiguration;
|
||||
|
||||
/**
|
||||
* @param ddiSecurityConfiguration
|
||||
* the security configuration which holds the configuration if
|
||||
* anonymous is enabled or not
|
||||
*/
|
||||
public ControllerPreAuthenticatedAnonymousFilter(final DdiSecurityProperties ddiSecurityConfiguration) {
|
||||
this.ddiSecurityConfiguration = ddiSecurityConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), secruityToken.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), secruityToken.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnable(final TenantSecurityToken secruityToken) {
|
||||
return ddiSecurityConfiguration.getAuthentication().getAnonymous().isEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -109,6 +109,7 @@ public class PreAuthTokenSourceTrustAuthenticationProvider implements Authentica
|
||||
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);
|
||||
successToken.setDetails(tokenDetails);
|
||||
|
||||
@@ -8,7 +8,12 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
/**
|
||||
* Interface for Pre Authenfication.
|
||||
@@ -45,4 +50,16 @@ public interface PreAuthenficationFilter {
|
||||
*/
|
||||
HeaderAuthentication getPreAuthenticatedCredentials(TenantSecurityToken secruityToken);
|
||||
|
||||
/**
|
||||
* Allows to add additional authorities to the successful authenticated
|
||||
* token.
|
||||
*
|
||||
* @return the authorities granted to the principal, or an empty collection
|
||||
* if the token has not been authenticated. Never null.
|
||||
* @see Authentication#getAuthorities()
|
||||
*/
|
||||
default Collection<GrantedAuthority> getSuccessfulAuthenticationAuthorities() {
|
||||
return Collections.emptyList();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user