Initial check in accordance with Parallel IP
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* 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.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
|
||||
/**
|
||||
* An abstraction for all controller based security to parse the e.g. the tenant
|
||||
* name from the URL and the controller ID from the URL to do security checks
|
||||
* based on these information.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractHttpControllerAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractHttpControllerAuthenticationFilter.class);
|
||||
|
||||
private static final String TENANT_PLACE_HOLDER = "tenant";
|
||||
private static final String CONTROLLER_ID_PLACE_HOLDER = "controllerId";
|
||||
|
||||
/**
|
||||
* requestURIPathPattern the request URI path pattern in ANT style
|
||||
* containing the placeholder key for retrieving the principal from the URI
|
||||
* request. e.g."/{tenant}/controller/v1/{controllerId}
|
||||
*/
|
||||
private static final String CONTROLLER_REQUEST_ANT_PATTERN = "/{" + TENANT_PLACE_HOLDER + "}/controller/v1" + "/{"
|
||||
+ CONTROLLER_ID_PLACE_HOLDER + "}/**";
|
||||
|
||||
private static final String CONTROLLER_DL_REQUEST_ANT_PATTERN = "/{" + TENANT_PLACE_HOLDER
|
||||
+ "}/controller/artifacts/v1/**";
|
||||
protected SystemManagement systemManagement;
|
||||
protected TenantAware tenantAware;
|
||||
|
||||
private final AntPathMatcher pathExtractor;
|
||||
|
||||
private PreAuthenficationFilter abstractControllerAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* Constructor for sub-classes.
|
||||
*
|
||||
* @param systemManagement
|
||||
* the system management service
|
||||
* @param tenantAware
|
||||
* the tenant aware service
|
||||
*/
|
||||
public AbstractHttpControllerAuthenticationFilter(final SystemManagement systemManagement,
|
||||
final TenantAware tenantAware) {
|
||||
this.systemManagement = systemManagement;
|
||||
this.tenantAware = tenantAware;
|
||||
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 {
|
||||
|
||||
if (!(request instanceof HttpServletRequest)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables((HttpServletRequest) request);
|
||||
if (secruityToken == null) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
abstractControllerAuthenticationFilter = createControllerAuthenticationFilter();
|
||||
if (abstractControllerAuthenticationFilter.isEnable(secruityToken)
|
||||
&& SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
super.doFilter(request, response, chain);
|
||||
} else {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract PreAuthenficationFilter createControllerAuthenticationFilter();
|
||||
|
||||
/**
|
||||
* Extracts tenant and controllerId from the request URI as path variables.
|
||||
*
|
||||
* @param request
|
||||
* the Http request to extract the path variables.
|
||||
* @return the extracted {@link PathVariables} or {@code null} if the
|
||||
* request does not match the pattern and no variables could be
|
||||
* extracted
|
||||
*/
|
||||
protected TenantSecruityToken createTenantSecruityTokenVariables(final HttpServletRequest request) {
|
||||
final String requestURI = request.getRequestURI();
|
||||
|
||||
if (pathExtractor.match(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI)) {
|
||||
LOGGER.debug("retrieving principal from URI request {}", requestURI);
|
||||
final Map<String, String> extractUriTemplateVariables = pathExtractor
|
||||
.extractUriTemplateVariables(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI);
|
||||
final String controllerId = extractUriTemplateVariables.get(CONTROLLER_ID_PLACE_HOLDER);
|
||||
final String tenant = extractUriTemplateVariables.get(TENANT_PLACE_HOLDER);
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Parsed tenant {} and controllerId {} from path request {}", tenant, controllerId,
|
||||
requestURI);
|
||||
}
|
||||
return createTenantSecruityTokenVariables(request, tenant, controllerId);
|
||||
} else if (pathExtractor.match(request.getContextPath() + CONTROLLER_DL_REQUEST_ANT_PATTERN, requestURI)) {
|
||||
LOGGER.debug("retrieving path variables from URI request {}", requestURI);
|
||||
final Map<String, String> extractUriTemplateVariables = pathExtractor.extractUriTemplateVariables(
|
||||
request.getContextPath() + CONTROLLER_DL_REQUEST_ANT_PATTERN, requestURI);
|
||||
final String tenant = extractUriTemplateVariables.get(TENANT_PLACE_HOLDER);
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Parsed tenant {} from path request {}", tenant, requestURI);
|
||||
}
|
||||
return createTenantSecruityTokenVariables(request, tenant, "anonymous");
|
||||
} else {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("request {} does not match the path pattern {}, request gets ignored", requestURI,
|
||||
CONTROLLER_REQUEST_ANT_PATTERN);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private TenantSecruityToken createTenantSecruityTokenVariables(final HttpServletRequest request,
|
||||
final String tenant, final String controllerId) {
|
||||
final TenantSecruityToken secruityToken = new TenantSecruityToken(tenant, controllerId, "");
|
||||
final UnmodifiableIterator<String> forEnumeration = Iterators.forEnumeration(request.getHeaderNames());
|
||||
forEnumeration.forEachRemaining(header -> secruityToken.getHeaders().put(header, request.getHeader(header)));
|
||||
return secruityToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) {
|
||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables(request);
|
||||
if (secruityToken == null) {
|
||||
return null;
|
||||
}
|
||||
return abstractControllerAuthenticationFilter.getPreAuthenticatedPrincipal(secruityToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) {
|
||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables(request);
|
||||
if (secruityToken == null) {
|
||||
return null;
|
||||
}
|
||||
return abstractControllerAuthenticationFilter.getPreAuthenticatedCredentials(secruityToken);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
/**
|
||||
* An {@link AuthenticationDetailsSource} implementation which retrieves the
|
||||
* tenant from a request pattern {@link #TENANT_AWARE_CONTROLLER_PATTERN} and
|
||||
* stores the retrieved tenant in the {@link TenantAwareAuthenticationDetails}.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ControllerTenantAwareAuthenticationDetailsSource
|
||||
implements AuthenticationDetailsSource<HttpServletRequest, TenantAwareAuthenticationDetails> {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String TENANT_AWARE_CONTROLLER_PATTERN = "/{tenant}/controller/**";
|
||||
private static final Logger LOGGER = LoggerFactory
|
||||
.getLogger(ControllerTenantAwareAuthenticationDetailsSource.class);
|
||||
private static final String TENANT_PLACE_HOLDER = "tenant";
|
||||
private final AntPathMatcher pathExtractor;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ControllerTenantAwareAuthenticationDetailsSource() {
|
||||
pathExtractor = new AntPathMatcher();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.security.authentication.AuthenticationDetailsSource#
|
||||
* buildDetails(java. lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public TenantAwareAuthenticationDetails buildDetails(final HttpServletRequest request) {
|
||||
return new TenantAwareWebAuthenticationDetails(getTenantFromRequestUri(request), request.getRemoteAddr(), true);
|
||||
}
|
||||
|
||||
private String getTenantFromRequestUri(final HttpServletRequest request) {
|
||||
final String requestURI = request.getRequestURI();
|
||||
LOGGER.debug("retrieving tenant from URI request {}", requestURI);
|
||||
final String requestPathPattern = request.getContextPath() + TENANT_AWARE_CONTROLLER_PATTERN;
|
||||
if (!pathExtractor.match(requestPathPattern, requestURI)) {
|
||||
LOGGER.info("Controller request not matching tenant aware request pattern requestpath: {}, pattern {}",
|
||||
requestURI, TENANT_AWARE_CONTROLLER_PATTERN);
|
||||
return null;
|
||||
}
|
||||
final Map<String, String> extractUriTemplateVariables = pathExtractor
|
||||
.extractUriTemplateVariables(requestPathPattern, requestURI);
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Parsed path variables {} using tenant {}", extractUriTemplateVariables,
|
||||
extractUriTemplateVariables.get(TENANT_PLACE_HOLDER));
|
||||
}
|
||||
return extractUriTemplateVariables.get(TENANT_PLACE_HOLDER);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* 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.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
|
||||
/**
|
||||
* An pre-authenticated processing filter which extracts (if enabled through
|
||||
* configuration) the possibility to authenticate a target based on its target
|
||||
* security-token with the {@code Authorization} HTTP header.
|
||||
* {@code Example Header: Authorization: TargetToken
|
||||
* 5d8fSD54fdsFG98DDsa.}
|
||||
*
|
||||
* The {@code Authorization} header is a HTTP standard and reverse proxy or
|
||||
* other proxies will keep the Authorization headers untouched instead of maybe
|
||||
* custom headers which have then weird side-effects. Furthermore frameworks are
|
||||
* aware of the sensitivity of the Authorization header and do not log it and
|
||||
* store it somewhere.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HttpControllerPreAuthenticateSecurityTokenFilter extends AbstractHttpControllerAuthenticationFilter {
|
||||
|
||||
private final ControllerManagement controllerManagement;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param systemManagement
|
||||
* the system management service to retrieve configuration
|
||||
* properties
|
||||
* @param tenantAware
|
||||
* the tenant aware service to get configuration for the specific
|
||||
* tenant
|
||||
* @param controllerManagement
|
||||
* the controller management to retrieve the specific target
|
||||
* security token to verify
|
||||
*/
|
||||
public HttpControllerPreAuthenticateSecurityTokenFilter(final SystemManagement systemManagement,
|
||||
final TenantAware tenantAware, final ControllerManagement controllerManagement) {
|
||||
super(systemManagement, tenantAware);
|
||||
this.controllerManagement = controllerManagement;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreAuthenficationFilter createControllerAuthenticationFilter() {
|
||||
return new ControllerPreAuthenticateSecurityTokenFilter(systemManagement, controllerManagement, tenantAware);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
|
||||
/**
|
||||
* Extract the {@code Authorization} header is a HTTP standard and reverse proxy
|
||||
* or other proxies will keep the Authorization headers untouched instead of
|
||||
* maybe custom headers which have then weird side-effects. Furthermore
|
||||
* frameworks are aware of the sensitivity of the Authorization header and do
|
||||
* not log it and store it somewhere.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HttpControllerPreAuthenticatedGatewaySecurityTokenFilter
|
||||
extends AbstractHttpControllerAuthenticationFilter {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param systemManagement
|
||||
* the system management service to retrieve configuration
|
||||
* properties
|
||||
* @param tenantAware
|
||||
* the tenant aware service to get configuration for the specific
|
||||
* tenant
|
||||
*/
|
||||
public HttpControllerPreAuthenticatedGatewaySecurityTokenFilter(final SystemManagement systemManagement,
|
||||
final TenantAware tenantAware) {
|
||||
super(systemManagement, tenantAware);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreAuthenficationFilter createControllerAuthenticationFilter() {
|
||||
return new ControllerPreAuthenticatedGatewaySecurityTokenFilter(systemManagement, tenantAware);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
|
||||
/**
|
||||
* An pre-authenticated processing filter which extracts the principal from a
|
||||
* request URI and the credential from a request header.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HttpControllerPreAuthenticatedSecurityHeaderFilter extends AbstractHttpControllerAuthenticationFilter {
|
||||
|
||||
private final String caCommonNameHeader;
|
||||
private final String caAuthorityNameHeader;
|
||||
|
||||
/**
|
||||
* Creates a new {@link ControllerPreAuthenticatedSecurityHeaderFilter}, in
|
||||
* case the HTTP request matches the given pattern the principal is parsed
|
||||
* from the HTTP request with the given URI pattern, in case the URI pattern
|
||||
* does not match the current request then only the existence of the
|
||||
* configured header field is checked.
|
||||
*
|
||||
* @param caCommonNameHeader
|
||||
* the http-header which holds the common-name of the certificate
|
||||
* @param caAuthorityNameHeader
|
||||
* the http-header which holds the ca-authority name of the
|
||||
* certificate
|
||||
* @param systemManagement
|
||||
* the system management service to retrieve configuration
|
||||
* properties to check if the header authentication is enabled
|
||||
* for this tenant
|
||||
* @param tenantAware
|
||||
* the tenant aware service to get configuration for the specific
|
||||
* tenant
|
||||
*/
|
||||
public HttpControllerPreAuthenticatedSecurityHeaderFilter(final String caCommonNameHeader,
|
||||
final String caAuthorityNameHeader, final SystemManagement systemManagement,
|
||||
final TenantAware tenantAware) {
|
||||
super(systemManagement, tenantAware);
|
||||
this.caCommonNameHeader = caCommonNameHeader;
|
||||
this.caAuthorityNameHeader = caAuthorityNameHeader;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PreAuthenficationFilter createControllerAuthenticationFilter() {
|
||||
return new ControllerPreAuthenticatedSecurityHeaderFilter(caCommonNameHeader, caAuthorityNameHeader,
|
||||
systemManagement, tenantAware);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||
|
||||
/**
|
||||
* Extracts download or upload id from the request URI secruity token and set
|
||||
* the security context.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HttpDownloadAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter {
|
||||
|
||||
public static final String REQUEST_ID_REGEX_PATTERN = ".*\\/downloadId\\/.*";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(HttpDownloadAuthenticationFilter.class);
|
||||
|
||||
private final Pattern pattern;
|
||||
private final Cache cache;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param cache
|
||||
* the cache
|
||||
*/
|
||||
public HttpDownloadAuthenticationFilter(final Cache cache) {
|
||||
this.cache = cache;
|
||||
this.pattern = Pattern.compile(REQUEST_ID_REGEX_PATTERN);
|
||||
|
||||
}
|
||||
|
||||
private Object getDownloadByUri(final String requestURI) {
|
||||
final Matcher matcher = pattern.matcher(requestURI);
|
||||
if (!matcher.matches()) {
|
||||
return null;
|
||||
}
|
||||
LOGGER.debug("retrieving id from URI request {}", requestURI);
|
||||
final String[] groups = requestURI.split("\\/");
|
||||
final String id = groups[groups.length - 1];
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
return cache.get(id).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) {
|
||||
return getDownloadByUri(request.getRequestURI());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) {
|
||||
return getDownloadByUri(request.getRequestURI());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user