fix typo of class TenantSecurityToken and handle authentication message
based on FileResource not only on SHA1 hash Signed-off-by: Michael Hirsch <michael.hirsch@bosch-si.com>
This commit is contained in:
@@ -13,7 +13,7 @@ import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
@@ -100,7 +100,7 @@ public class AmqpControllerAuthentfication {
|
||||
* the authentication request object
|
||||
* @return the authentfication object
|
||||
*/
|
||||
public Authentication doAuthenticate(final TenantSecruityToken secruityToken) {
|
||||
public Authentication doAuthenticate(final TenantSecurityToken secruityToken) {
|
||||
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(null, null);
|
||||
for (final PreAuthenficationFilter filter : filterChain) {
|
||||
final PreAuthenticatedAuthenticationToken authenticationRest = createAuthentication(filter, secruityToken);
|
||||
@@ -115,7 +115,7 @@ public class AmqpControllerAuthentfication {
|
||||
}
|
||||
|
||||
private static PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthenficationFilter filter,
|
||||
final TenantSecruityToken secruityToken) {
|
||||
final TenantSecurityToken secruityToken) {
|
||||
|
||||
if (!filter.isEnable(secruityToken)) {
|
||||
return null;
|
||||
|
||||
@@ -27,8 +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.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
@@ -157,25 +158,29 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
private Message handleAuthentifiactionMessage(final Message message) {
|
||||
final DownloadResponse authentificationResponse = new DownloadResponse();
|
||||
final MessageProperties messageProperties = message.getMessageProperties();
|
||||
final TenantSecruityToken secruityToken = convertMessage(message, TenantSecruityToken.class);
|
||||
final String sha1 = secruityToken.getSha1();
|
||||
final TenantSecurityToken secruityToken = convertMessage(message,
|
||||
TenantSecurityToken.class);
|
||||
final FileResource fileResource = secruityToken.getFileResource();
|
||||
try {
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken));
|
||||
final LocalArtifact localArtifact = artifactManagement
|
||||
.findFirstLocalArtifactsBySHA1(secruityToken.getSha1());
|
||||
|
||||
final LocalArtifact localArtifact = findLocalArtifactByFileResource(fileResource);
|
||||
|
||||
if (localArtifact == null) {
|
||||
throw new EntityNotFoundException();
|
||||
}
|
||||
|
||||
// check action for this download purposes, the method will throw an
|
||||
// EntityNotFoundException in case the controller is not allowed to
|
||||
// download this file
|
||||
// because it's not assigned to an action and not assigned to this
|
||||
// controller.
|
||||
final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule(
|
||||
secruityToken.getControllerId(), localArtifact.getSoftwareModule());
|
||||
LOG.info("Found action for download authentication request action: {}, sha1: {}", action,
|
||||
secruityToken.getSha1());
|
||||
// download this file because it's not assigned to an action and not
|
||||
// assigned to this controller. Otherwise no controllerId is set =
|
||||
// anonymous download
|
||||
if (secruityToken.getControllerId() != null) {
|
||||
final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule(
|
||||
secruityToken.getControllerId(), localArtifact.getSoftwareModule());
|
||||
LOG.info("Found action for download authentication request action: {}, resource: {}", action,
|
||||
secruityToken.getFileResource());
|
||||
}
|
||||
|
||||
final Artifact artifact = convertDbArtifact(artifactManagement.loadLocalArtifactBinary(localArtifact));
|
||||
if (artifact == null) {
|
||||
@@ -183,7 +188,9 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
}
|
||||
authentificationResponse.setArtifact(artifact);
|
||||
final String downloadId = UUID.randomUUID().toString();
|
||||
final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1, sha1);
|
||||
// SHA1 key is set, download by SHA1
|
||||
final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1,
|
||||
localArtifact.getSha1Hash());
|
||||
cache.put(downloadId, downloadCache);
|
||||
authentificationResponse
|
||||
.setDownloadUrl(UriComponentsBuilder.fromUri(hostnameResolver.resolveHostname().toURI())
|
||||
@@ -198,7 +205,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
authentificationResponse.setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
||||
authentificationResponse.setMessage("Building download URI failed");
|
||||
} catch (final EntityNotFoundException e) {
|
||||
final String errorMessage = "Artifact with sha1 " + sha1 + "not found ";
|
||||
final String errorMessage = "Artifact for resource " + fileResource + "not found ";
|
||||
LOG.warn(errorMessage, e);
|
||||
authentificationResponse.setResponseCode(HttpStatus.NOT_FOUND.value());
|
||||
authentificationResponse.setMessage(errorMessage);
|
||||
@@ -207,6 +214,23 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
return getMessageConverter().toMessage(authentificationResponse, messageProperties);
|
||||
}
|
||||
|
||||
private LocalArtifact findLocalArtifactByFileResource(final FileResource fileResource) {
|
||||
LocalArtifact localArtifact = null;
|
||||
if (fileResource.getSha1() != null) {
|
||||
localArtifact = artifactManagement.findFirstLocalArtifactsBySHA1(fileResource.getSha1());
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
return localArtifact;
|
||||
}
|
||||
|
||||
private static Artifact convertDbArtifact(final DbArtifact dbArtifact) {
|
||||
final Artifact artifact = new Artifact();
|
||||
artifact.setSize(dbArtifact.getSize());
|
||||
|
||||
@@ -19,7 +19,8 @@ import static org.mockito.Mockito.when;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
@@ -105,7 +106,8 @@ public class AmqpControllerAuthenticationTest {
|
||||
@Test
|
||||
@Description("Tests authentication manager without principal")
|
||||
public void testAuthenticationeBadCredantialsWithoutPricipal() {
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.sha1("12345"));
|
||||
try {
|
||||
authenticationManager.doAuthenticate(securityToken);
|
||||
fail("BadCredentialsException was excepeted since principal was missing");
|
||||
@@ -118,11 +120,12 @@ public class AmqpControllerAuthenticationTest {
|
||||
@Test
|
||||
@Description("Tests authentication manager without wrong credential")
|
||||
public void testAuthenticationBadCredantialsWithWrongCredential() {
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.sha1("12345"));
|
||||
when(tenantConfigurationManagement.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
securityToken.getHeaders().put(TenantSecruityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLLER_ID);
|
||||
securityToken.getHeaders().put(TenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLLER_ID);
|
||||
try {
|
||||
authenticationManager.doAuthenticate(securityToken);
|
||||
fail("BadCredentialsException was excepeted due to wrong credential");
|
||||
@@ -135,11 +138,12 @@ public class AmqpControllerAuthenticationTest {
|
||||
@Test
|
||||
@Description("Tests authentication successfull")
|
||||
public void testSuccessfullAuthentication() {
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.sha1("12345"));
|
||||
when(tenantConfigurationManagement.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
securityToken.getHeaders().put(TenantSecruityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLLER_ID);
|
||||
securityToken.getHeaders().put(TenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLLER_ID);
|
||||
final Authentication authentication = authenticationManager.doAuthenticate(securityToken);
|
||||
assertThat(authentication).isNotNull();
|
||||
}
|
||||
@@ -149,7 +153,8 @@ public class AmqpControllerAuthenticationTest {
|
||||
public void testAuthenticationMessageBadCredantialsWithoutPricipal() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.sha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
@@ -167,11 +172,12 @@ public class AmqpControllerAuthenticationTest {
|
||||
@Description("Tests authentication message without wrong credential")
|
||||
public void testAuthenticationMessageBadCredantialsWithWrongCredential() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.sha1("12345"));
|
||||
when(tenantConfigurationManagement.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
securityToken.getHeaders().put(TenantSecruityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLLER_ID);
|
||||
securityToken.getHeaders().put(TenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken 12" + CONTROLLLER_ID);
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
@@ -189,11 +195,12 @@ public class AmqpControllerAuthenticationTest {
|
||||
@Description("Tests authentication message successfull")
|
||||
public void testSuccessfullMessageAuthentication() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.sha1("12345"));
|
||||
when(tenantConfigurationManagement.getConfigurationValue(
|
||||
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
|
||||
.thenReturn(CONFIG_VALUE_TRUE);
|
||||
securityToken.getHeaders().put(TenantSecruityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLLER_ID);
|
||||
securityToken.getHeaders().put(TenantSecurityToken.AUTHORIZATION_HEADER, "TargetToken " + CONTROLLLER_ID);
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
@@ -263,7 +264,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Description("Tests that an download request is denied for an artifact which does not exists")
|
||||
public void authenticationRequestDeniedForArtifactWhichDoesNotExists() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, "123", "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
@@ -282,7 +283,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Description("Tests that an download request is denied for an artifact which is not assigned to the requested target")
|
||||
public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, "123", "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
@@ -306,7 +307,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target")
|
||||
public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, "123", "12345");
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.dmf.json.model;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* JSON representation to authenticate a tenant.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class TenantSecruityToken {
|
||||
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
public static final String COAP_AUTHORIZATION_HEADER = "Coap-Authorization";
|
||||
public static final String COAP_TOKEN_VALUE = "CoapToken";
|
||||
|
||||
@JsonProperty
|
||||
private final String tenant;
|
||||
@JsonProperty
|
||||
private final String controllerId;
|
||||
@JsonProperty(required = false)
|
||||
private Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
@JsonProperty(required = false)
|
||||
private final String sha1;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant for the security token
|
||||
* @param controllerId
|
||||
* the ID of the controller for the security token
|
||||
* @param sha1
|
||||
* the sha1 of authentication
|
||||
*/
|
||||
@JsonCreator
|
||||
public TenantSecruityToken(@JsonProperty("tenant") final String tenant,
|
||||
@JsonProperty("controllerId") final String controllerId, @JsonProperty("sha1") final String sha1) {
|
||||
this.tenant = tenant;
|
||||
this.controllerId = controllerId;
|
||||
this.sha1 = sha1;
|
||||
}
|
||||
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
public String getControllerId() {
|
||||
return controllerId;
|
||||
}
|
||||
|
||||
public Map<String, String> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public String getSha1() {
|
||||
return sha1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a header value.
|
||||
*
|
||||
* @param name
|
||||
* of header
|
||||
* @return the value
|
||||
*/
|
||||
public String getHeader(final String name) {
|
||||
return headers.get(name);
|
||||
}
|
||||
|
||||
public void setHeaders(final Map<String, String> headers) {
|
||||
this.headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
this.headers.putAll(headers);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* 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.dmf.json.model;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* JSON representation to authenticate a tenant.
|
||||
*/
|
||||
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class TenantSecurityToken {
|
||||
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
public static final String COAP_AUTHORIZATION_HEADER = "Coap-Authorization";
|
||||
public static final String COAP_TOKEN_VALUE = "CoapToken";
|
||||
|
||||
@JsonProperty
|
||||
private final String tenant;
|
||||
@JsonProperty
|
||||
private final String controllerId;
|
||||
@JsonProperty(required = false)
|
||||
private Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
@JsonProperty(required = false)
|
||||
private final FileResource fileResource;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant for the security token
|
||||
* @param controllerId
|
||||
* the ID of the controller for the security token
|
||||
* @param fileResource
|
||||
* the file to obtain
|
||||
*/
|
||||
@JsonCreator
|
||||
public TenantSecurityToken(@JsonProperty("tenant") final String tenant,
|
||||
@JsonProperty("controllerId") final String controllerId,
|
||||
@JsonProperty("fileResource") final FileResource fileResource) {
|
||||
this.tenant = tenant;
|
||||
this.controllerId = controllerId;
|
||||
this.fileResource = fileResource;
|
||||
}
|
||||
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
public String getControllerId() {
|
||||
return controllerId;
|
||||
}
|
||||
|
||||
public Map<String, String> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public FileResource getFileResource() {
|
||||
return fileResource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a header value.
|
||||
*
|
||||
* @param name
|
||||
* of header
|
||||
* @return the value
|
||||
*/
|
||||
public String getHeader(final String name) {
|
||||
return headers.get(name);
|
||||
}
|
||||
|
||||
public void setHeaders(final Map<String, String> headers) {
|
||||
this.headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
this.headers.putAll(headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* File resource descriptor which is used to ask for the resource to
|
||||
* download e.g. The lookup of the file can be different e.g. by SHA1 hash
|
||||
* or by filename.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class FileResource {
|
||||
@JsonProperty(required = false)
|
||||
private String sha1;
|
||||
@JsonProperty(required = false)
|
||||
private String filename;
|
||||
@JsonProperty(required = false)
|
||||
private Long artifactId;
|
||||
|
||||
public String getSha1() {
|
||||
return sha1;
|
||||
}
|
||||
|
||||
public void setSha1(final String sha1) {
|
||||
this.sha1 = sha1;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public void setFilename(final String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public Long getArtifactId() {
|
||||
return artifactId;
|
||||
}
|
||||
|
||||
public void setArtifactId(final Long artifactId) {
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
/**
|
||||
* factory method to create a file resource for an SHA1 lookup.
|
||||
*
|
||||
* @param sha1
|
||||
* the SHA1 key of the file to obtain
|
||||
* @return the {@link FileResource} with SHA1 key set
|
||||
*/
|
||||
public static FileResource sha1(final String sha1) {
|
||||
final FileResource resource = new FileResource();
|
||||
resource.sha1 = sha1;
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* factory method to create a file resource for an filename lookup.
|
||||
*
|
||||
* @param filename
|
||||
* the filename of the file to obtain
|
||||
* @return the {@link FileResource} with filename set
|
||||
*/
|
||||
public static FileResource filename(final String filename) {
|
||||
final FileResource resource = new FileResource();
|
||||
resource.filename = filename;
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* factory method to create a file resource for an artifactId lookup.
|
||||
*
|
||||
* @param artifactId
|
||||
* the artifactId of the file to obtain
|
||||
* @return the {@link FileResource} with artifactId set
|
||||
*/
|
||||
public static FileResource artifactId(final Long artifactId) {
|
||||
final FileResource resource = new FileResource();
|
||||
resource.artifactId = artifactId;
|
||||
return resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FileResource [sha1=" + sha1 + ", filename=" + filename + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,8 @@ 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.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
@@ -96,7 +97,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
return;
|
||||
}
|
||||
|
||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables((HttpServletRequest) request);
|
||||
final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables((HttpServletRequest) request);
|
||||
if (secruityToken == null) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
@@ -121,7 +122,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
* request does not match the pattern and no variables could be
|
||||
* extracted
|
||||
*/
|
||||
protected TenantSecruityToken createTenantSecruityTokenVariables(final HttpServletRequest request) {
|
||||
protected TenantSecurityToken createTenantSecruityTokenVariables(final HttpServletRequest request) {
|
||||
final String requestURI = request.getRequestURI();
|
||||
|
||||
if (pathExtractor.match(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI)) {
|
||||
@@ -153,9 +154,9 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
}
|
||||
}
|
||||
|
||||
private TenantSecruityToken createTenantSecruityTokenVariables(final HttpServletRequest request,
|
||||
private TenantSecurityToken createTenantSecruityTokenVariables(final HttpServletRequest request,
|
||||
final String tenant, final String controllerId) {
|
||||
final TenantSecruityToken secruityToken = new TenantSecruityToken(tenant, controllerId, "");
|
||||
final TenantSecurityToken secruityToken = new TenantSecurityToken(tenant, controllerId, FileResource.sha1(""));
|
||||
final UnmodifiableIterator<String> forEnumeration = Iterators.forEnumeration(request.getHeaderNames());
|
||||
forEnumeration.forEachRemaining(header -> secruityToken.getHeaders().put(header, request.getHeader(header)));
|
||||
return secruityToken;
|
||||
@@ -163,7 +164,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
|
||||
@Override
|
||||
protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) {
|
||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables(request);
|
||||
final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables(request);
|
||||
if (secruityToken == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -172,7 +173,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
|
||||
|
||||
@Override
|
||||
protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) {
|
||||
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables(request);
|
||||
final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables(request);
|
||||
if (secruityToken == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -321,7 +321,8 @@ public class ArtifactManagement {
|
||||
}
|
||||
|
||||
boolean artifactIsOnlyUsedByOneSoftwareModule = true;
|
||||
for (LocalArtifact lArtifact : localArtifactRepository.findByGridFsFileName(existing.getGridFsFileName())) {
|
||||
for (final LocalArtifact lArtifact : localArtifactRepository
|
||||
.findByGridFsFileName(existing.getGridFsFileName())) {
|
||||
if (!lArtifact.getSoftwareModule().isDeleted()
|
||||
&& lArtifact.getSoftwareModule().getId() != existing.getSoftwareModule().getId()) {
|
||||
artifactIsOnlyUsedByOneSoftwareModule = false;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||
@@ -42,15 +42,15 @@ public abstract class AbstractControllerAuthenticationFilter implements PreAuthe
|
||||
protected abstract TenantConfigurationKey getTenantConfigurationKey();
|
||||
|
||||
@Override
|
||||
public boolean isEnable(final TenantSecruityToken secruityToken) {
|
||||
public boolean isEnable(final TenantSecurityToken secruityToken) {
|
||||
return tenantAware.runAsTenant(secruityToken.getTenant(), configurationKeyTenantRunner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecruityToken secruityToken);
|
||||
public abstract HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecurityToken secruityToken);
|
||||
|
||||
@Override
|
||||
public abstract HeaderAuthentication getPreAuthenticatedCredentials(TenantSecruityToken secruityToken);
|
||||
public abstract HeaderAuthentication getPreAuthenticatedCredentials(TenantSecurityToken secruityToken);
|
||||
|
||||
private final class SecurityConfigurationKeyTenantRunner implements TenantAware.TenantRunner<Boolean> {
|
||||
@Override
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
|
||||
/**
|
||||
* A Filter for device which download via coap.
|
||||
@@ -19,19 +19,19 @@ import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
public class CoapAnonymousPreAuthenticatedFilter implements PreAuthenficationFilter {
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) {
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecruityToken.COAP_TOKEN_VALUE);
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecurityToken.COAP_TOKEN_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) {
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecruityToken.COAP_TOKEN_VALUE);
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecurityToken.COAP_TOKEN_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnable(final TenantSecruityToken secruityToken) {
|
||||
final String authHeader = secruityToken.getHeader(TenantSecruityToken.COAP_AUTHORIZATION_HEADER);
|
||||
return TenantSecruityToken.COAP_TOKEN_VALUE.equals(authHeader);
|
||||
public boolean isEnable(final TenantSecurityToken secruityToken) {
|
||||
final String authHeader = secruityToken.getHeader(TenantSecurityToken.COAP_AUTHORIZATION_HEADER);
|
||||
return TenantSecurityToken.COAP_TOKEN_VALUE.equals(authHeader);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
@@ -67,8 +67,8 @@ public class ControllerPreAuthenticateSecurityTokenFilter extends AbstractContro
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) {
|
||||
final String authHeader = secruityToken.getHeader(TenantSecruityToken.AUTHORIZATION_HEADER);
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||
final String authHeader = secruityToken.getHeader(TenantSecurityToken.AUTHORIZATION_HEADER);
|
||||
if ((authHeader != null) && authHeader.startsWith(TARGET_SECURITY_TOKEN_AUTH_SCHEME)) {
|
||||
LOGGER.debug("found authorization header with scheme {} using target security token for authentication",
|
||||
TARGET_SECURITY_TOKEN_AUTH_SCHEME);
|
||||
@@ -81,7 +81,7 @@ public class ControllerPreAuthenticateSecurityTokenFilter extends AbstractContro
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) {
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||
final String securityToken = tenantAware.runAsTenant(secruityToken.getTenant(),
|
||||
new GetSecurityTokenTenantRunner(secruityToken.getTenant(), secruityToken.getControllerId()));
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), securityToken);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||
@@ -56,8 +56,8 @@ public class ControllerPreAuthenticatedGatewaySecurityTokenFilter extends Abstra
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) {
|
||||
final String authHeader = secruityToken.getHeader(TenantSecruityToken.AUTHORIZATION_HEADER);
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||
final String authHeader = secruityToken.getHeader(TenantSecurityToken.AUTHORIZATION_HEADER);
|
||||
if ((authHeader != null) && authHeader.startsWith(GATEWAY_SECURITY_TOKEN_AUTH_SCHEME)) {
|
||||
LOGGER.debug("found authorization header with scheme {} using target security token for authentication",
|
||||
GATEWAY_SECURITY_TOKEN_AUTH_SCHEME);
|
||||
@@ -71,7 +71,7 @@ public class ControllerPreAuthenticatedGatewaySecurityTokenFilter extends Abstra
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) {
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||
final String gatewayToken = tenantAware.runAsTenant(secruityToken.getTenant(),
|
||||
gatewaySecurityTokenKeyConfigRunner);
|
||||
return new HeaderAuthentication(secruityToken.getControllerId(), gatewayToken);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||
@@ -18,7 +18,7 @@ import org.slf4j.LoggerFactory;
|
||||
/**
|
||||
* An pre-authenticated processing filter which extracts the principal from a
|
||||
* request URI and the credential from a request header in a the
|
||||
* {@link TenantSecruityToken}.
|
||||
* {@link TenantSecurityToken}.
|
||||
*
|
||||
*
|
||||
*
|
||||
@@ -75,7 +75,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) {
|
||||
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
|
||||
// retrieve the common name header and the authority name header from
|
||||
// the http request and
|
||||
// combine them together
|
||||
@@ -97,7 +97,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) {
|
||||
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
|
||||
final String authorityNameConfigurationValue = tenantAware.runAsTenant(secruityToken.getTenant(),
|
||||
sslIssuerNameConfigTenantRunner);
|
||||
String controllerId = secruityToken.getControllerId();
|
||||
@@ -117,7 +117,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
|
||||
* It's ok if we find the the hash in any the trusted CA chain to accept
|
||||
* this request for this tenant.
|
||||
*/
|
||||
private String getIssuerHashHeader(final TenantSecruityToken secruityToken, final String knownIssuerHash) {
|
||||
private String getIssuerHashHeader(final TenantSecurityToken secruityToken, final String knownIssuerHash) {
|
||||
// iterate over the headers until we get a null header.
|
||||
int iHeader = 1;
|
||||
String foundHash;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.security;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
|
||||
/**
|
||||
* Interface for Pre Authenfication.
|
||||
@@ -25,7 +25,7 @@ public interface PreAuthenficationFilter {
|
||||
* the secruity info
|
||||
* @return <true> is enabled <false> diabled
|
||||
*/
|
||||
boolean isEnable(TenantSecruityToken secruityToken);
|
||||
boolean isEnable(TenantSecurityToken secruityToken);
|
||||
|
||||
/**
|
||||
* Extract the principal information from the current secruityToken.
|
||||
@@ -34,7 +34,7 @@ public interface PreAuthenficationFilter {
|
||||
* the secruityToken
|
||||
* @return the extracted tenant and controller id
|
||||
*/
|
||||
HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecruityToken secruityToken);
|
||||
HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecurityToken secruityToken);
|
||||
|
||||
/**
|
||||
* Extract the principal credentials from the current secruityToken.
|
||||
@@ -43,6 +43,6 @@ public interface PreAuthenficationFilter {
|
||||
* the secruityToken
|
||||
* @return the extracted tenant and controller id
|
||||
*/
|
||||
HeaderAuthentication getPreAuthenticatedCredentials(TenantSecruityToken secruityToken);
|
||||
HeaderAuthentication getPreAuthenticatedCredentials(TenantSecurityToken secruityToken);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user