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:
Michael Hirsch
2016-03-23 10:23:35 +01:00
parent a3295b518d
commit cdac7185c4
14 changed files with 279 additions and 163 deletions

View File

@@ -13,7 +13,7 @@ import java.util.List;
import javax.annotation.PostConstruct; 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.im.authentication.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
@@ -100,7 +100,7 @@ public class AmqpControllerAuthentfication {
* the authentication request object * the authentication request object
* @return the authentfication object * @return the authentfication object
*/ */
public Authentication doAuthenticate(final TenantSecruityToken secruityToken) { public Authentication doAuthenticate(final TenantSecurityToken secruityToken) {
PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(null, null); PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(null, null);
for (final PreAuthenficationFilter filter : filterChain) { for (final PreAuthenficationFilter filter : filterChain) {
final PreAuthenticatedAuthenticationToken authenticationRest = createAuthentication(filter, secruityToken); final PreAuthenticatedAuthenticationToken authenticationRest = createAuthentication(filter, secruityToken);
@@ -115,7 +115,7 @@ public class AmqpControllerAuthentfication {
} }
private static PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthenficationFilter filter, private static PreAuthenticatedAuthenticationToken createAuthentication(final PreAuthenficationFilter filter,
final TenantSecruityToken secruityToken) { final TenantSecurityToken secruityToken) {
if (!filter.isEnable(secruityToken)) { if (!filter.isEnable(secruityToken)) {
return null; return null;

View File

@@ -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.ActionUpdateStatus;
import org.eclipse.hawkbit.dmf.json.model.Artifact; import org.eclipse.hawkbit.dmf.json.model.Artifact;
import org.eclipse.hawkbit.dmf.json.model.ArtifactHash; 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.DownloadResponse;
import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
@@ -157,25 +158,29 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
private Message handleAuthentifiactionMessage(final Message message) { private Message handleAuthentifiactionMessage(final Message message) {
final DownloadResponse authentificationResponse = new DownloadResponse(); final DownloadResponse authentificationResponse = new DownloadResponse();
final MessageProperties messageProperties = message.getMessageProperties(); final MessageProperties messageProperties = message.getMessageProperties();
final TenantSecruityToken secruityToken = convertMessage(message, TenantSecruityToken.class); final TenantSecurityToken secruityToken = convertMessage(message,
final String sha1 = secruityToken.getSha1(); TenantSecurityToken.class);
final FileResource fileResource = secruityToken.getFileResource();
try { try {
SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken)); SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken));
final LocalArtifact localArtifact = artifactManagement
.findFirstLocalArtifactsBySHA1(secruityToken.getSha1()); final LocalArtifact localArtifact = findLocalArtifactByFileResource(fileResource);
if (localArtifact == null) { if (localArtifact == null) {
throw new EntityNotFoundException(); throw new EntityNotFoundException();
} }
// check action for this download purposes, the method will throw an // check action for this download purposes, the method will throw an
// EntityNotFoundException in case the controller is not allowed to // EntityNotFoundException in case the controller is not allowed to
// download this file // download this file because it's not assigned to an action and not
// because it's not assigned to an action and not assigned to this // assigned to this controller. Otherwise no controllerId is set =
// controller. // anonymous download
final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule( if (secruityToken.getControllerId() != null) {
secruityToken.getControllerId(), localArtifact.getSoftwareModule()); final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule(
LOG.info("Found action for download authentication request action: {}, sha1: {}", action, secruityToken.getControllerId(), localArtifact.getSoftwareModule());
secruityToken.getSha1()); LOG.info("Found action for download authentication request action: {}, resource: {}", action,
secruityToken.getFileResource());
}
final Artifact artifact = convertDbArtifact(artifactManagement.loadLocalArtifactBinary(localArtifact)); final Artifact artifact = convertDbArtifact(artifactManagement.loadLocalArtifactBinary(localArtifact));
if (artifact == null) { if (artifact == null) {
@@ -183,7 +188,9 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
} }
authentificationResponse.setArtifact(artifact); authentificationResponse.setArtifact(artifact);
final String downloadId = UUID.randomUUID().toString(); 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); cache.put(downloadId, downloadCache);
authentificationResponse authentificationResponse
.setDownloadUrl(UriComponentsBuilder.fromUri(hostnameResolver.resolveHostname().toURI()) .setDownloadUrl(UriComponentsBuilder.fromUri(hostnameResolver.resolveHostname().toURI())
@@ -198,7 +205,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
authentificationResponse.setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); authentificationResponse.setResponseCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
authentificationResponse.setMessage("Building download URI failed"); authentificationResponse.setMessage("Building download URI failed");
} catch (final EntityNotFoundException e) { } 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); LOG.warn(errorMessage, e);
authentificationResponse.setResponseCode(HttpStatus.NOT_FOUND.value()); authentificationResponse.setResponseCode(HttpStatus.NOT_FOUND.value());
authentificationResponse.setMessage(errorMessage); authentificationResponse.setMessage(errorMessage);
@@ -207,6 +214,23 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
return getMessageConverter().toMessage(authentificationResponse, messageProperties); 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) { private static Artifact convertDbArtifact(final DbArtifact dbArtifact) {
final Artifact artifact = new Artifact(); final Artifact artifact = new Artifact();
artifact.setSize(dbArtifact.getSize()); artifact.setSize(dbArtifact.getSize());

View File

@@ -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.MessageHeaderKey;
import org.eclipse.hawkbit.dmf.amqp.api.MessageType; import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse; 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.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
@@ -105,7 +106,8 @@ public class AmqpControllerAuthenticationTest {
@Test @Test
@Description("Tests authentication manager without principal") @Description("Tests authentication manager without principal")
public void testAuthenticationeBadCredantialsWithoutPricipal() { public void testAuthenticationeBadCredantialsWithoutPricipal() {
final TenantSecruityToken securityToken = new TenantSecruityToken(TENANT, CONTROLLLER_ID, "12345"); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
FileResource.sha1("12345"));
try { try {
authenticationManager.doAuthenticate(securityToken); authenticationManager.doAuthenticate(securityToken);
fail("BadCredentialsException was excepeted since principal was missing"); fail("BadCredentialsException was excepeted since principal was missing");
@@ -118,11 +120,12 @@ public class AmqpControllerAuthenticationTest {
@Test @Test
@Description("Tests authentication manager without wrong credential") @Description("Tests authentication manager without wrong credential")
public void testAuthenticationBadCredantialsWithWrongCredential() { 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( when(tenantConfigurationManagement.getConfigurationValue(
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class))) eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
.thenReturn(CONFIG_VALUE_TRUE); .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 { try {
authenticationManager.doAuthenticate(securityToken); authenticationManager.doAuthenticate(securityToken);
fail("BadCredentialsException was excepeted due to wrong credential"); fail("BadCredentialsException was excepeted due to wrong credential");
@@ -135,11 +138,12 @@ public class AmqpControllerAuthenticationTest {
@Test @Test
@Description("Tests authentication successfull") @Description("Tests authentication successfull")
public void testSuccessfullAuthentication() { 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( when(tenantConfigurationManagement.getConfigurationValue(
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class))) eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
.thenReturn(CONFIG_VALUE_TRUE); .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); final Authentication authentication = authenticationManager.doAuthenticate(securityToken);
assertThat(authentication).isNotNull(); assertThat(authentication).isNotNull();
} }
@@ -149,7 +153,8 @@ public class AmqpControllerAuthenticationTest {
public void testAuthenticationMessageBadCredantialsWithoutPricipal() { public void testAuthenticationMessageBadCredantialsWithoutPricipal() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); 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, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); messageProperties);
@@ -167,11 +172,12 @@ public class AmqpControllerAuthenticationTest {
@Description("Tests authentication message without wrong credential") @Description("Tests authentication message without wrong credential")
public void testAuthenticationMessageBadCredantialsWithWrongCredential() { public void testAuthenticationMessageBadCredantialsWithWrongCredential() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); 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( when(tenantConfigurationManagement.getConfigurationValue(
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class))) eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
.thenReturn(CONFIG_VALUE_TRUE); .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, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); messageProperties);
@@ -189,11 +195,12 @@ public class AmqpControllerAuthenticationTest {
@Description("Tests authentication message successfull") @Description("Tests authentication message successfull")
public void testSuccessfullMessageAuthentication() { public void testSuccessfullMessageAuthentication() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); 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( when(tenantConfigurationManagement.getConfigurationValue(
eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class))) eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class)))
.thenReturn(CONFIG_VALUE_TRUE); .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, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); messageProperties);

View File

@@ -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.ActionStatus;
import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus; import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse; 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.eventbus.event.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement; 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") @Description("Tests that an download request is denied for an artifact which does not exists")
public void authenticationRequestDeniedForArtifactWhichDoesNotExists() { public void authenticationRequestDeniedForArtifactWhichDoesNotExists() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); 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, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); 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") @Description("Tests that an download request is denied for an artifact which is not assigned to the requested target")
public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() { public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); 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, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); 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") @Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target")
public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException { public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException {
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); 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, final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
messageProperties); messageProperties);

View File

@@ -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);
}
}

View File

@@ -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 + "]";
}
}
}

View File

@@ -17,7 +17,8 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; 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.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -96,7 +97,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
return; return;
} }
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables((HttpServletRequest) request); final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables((HttpServletRequest) request);
if (secruityToken == null) { if (secruityToken == null) {
chain.doFilter(request, response); chain.doFilter(request, response);
return; return;
@@ -121,7 +122,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
* request does not match the pattern and no variables could be * request does not match the pattern and no variables could be
* extracted * extracted
*/ */
protected TenantSecruityToken createTenantSecruityTokenVariables(final HttpServletRequest request) { protected TenantSecurityToken createTenantSecruityTokenVariables(final HttpServletRequest request) {
final String requestURI = request.getRequestURI(); final String requestURI = request.getRequestURI();
if (pathExtractor.match(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI)) { 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 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()); final UnmodifiableIterator<String> forEnumeration = Iterators.forEnumeration(request.getHeaderNames());
forEnumeration.forEachRemaining(header -> secruityToken.getHeaders().put(header, request.getHeader(header))); forEnumeration.forEachRemaining(header -> secruityToken.getHeaders().put(header, request.getHeader(header)));
return secruityToken; return secruityToken;
@@ -163,7 +164,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
@Override @Override
protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) { protected Object getPreAuthenticatedPrincipal(final HttpServletRequest request) {
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables(request); final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables(request);
if (secruityToken == null) { if (secruityToken == null) {
return null; return null;
} }
@@ -172,7 +173,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
@Override @Override
protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) { protected Object getPreAuthenticatedCredentials(final HttpServletRequest request) {
final TenantSecruityToken secruityToken = createTenantSecruityTokenVariables(request); final TenantSecurityToken secruityToken = createTenantSecruityTokenVariables(request);
if (secruityToken == null) { if (secruityToken == null) {
return null; return null;
} }

View File

@@ -321,7 +321,8 @@ public class ArtifactManagement {
} }
boolean artifactIsOnlyUsedByOneSoftwareModule = true; boolean artifactIsOnlyUsedByOneSoftwareModule = true;
for (LocalArtifact lArtifact : localArtifactRepository.findByGridFsFileName(existing.getGridFsFileName())) { for (final LocalArtifact lArtifact : localArtifactRepository
.findByGridFsFileName(existing.getGridFsFileName())) {
if (!lArtifact.getSoftwareModule().isDeleted() if (!lArtifact.getSoftwareModule().isDeleted()
&& lArtifact.getSoftwareModule().getId() != existing.getSoftwareModule().getId()) { && lArtifact.getSoftwareModule().getId() != existing.getSoftwareModule().getId()) {
artifactIsOnlyUsedByOneSoftwareModule = false; artifactIsOnlyUsedByOneSoftwareModule = false;

View File

@@ -8,7 +8,7 @@
*/ */
package org.eclipse.hawkbit.security; 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.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
@@ -42,15 +42,15 @@ public abstract class AbstractControllerAuthenticationFilter implements PreAuthe
protected abstract TenantConfigurationKey getTenantConfigurationKey(); protected abstract TenantConfigurationKey getTenantConfigurationKey();
@Override @Override
public boolean isEnable(final TenantSecruityToken secruityToken) { public boolean isEnable(final TenantSecurityToken secruityToken) {
return tenantAware.runAsTenant(secruityToken.getTenant(), configurationKeyTenantRunner); return tenantAware.runAsTenant(secruityToken.getTenant(), configurationKeyTenantRunner);
} }
@Override @Override
public abstract HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecruityToken secruityToken); public abstract HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecurityToken secruityToken);
@Override @Override
public abstract HeaderAuthentication getPreAuthenticatedCredentials(TenantSecruityToken secruityToken); public abstract HeaderAuthentication getPreAuthenticatedCredentials(TenantSecurityToken secruityToken);
private final class SecurityConfigurationKeyTenantRunner implements TenantAware.TenantRunner<Boolean> { private final class SecurityConfigurationKeyTenantRunner implements TenantAware.TenantRunner<Boolean> {
@Override @Override

View File

@@ -8,7 +8,7 @@
*/ */
package org.eclipse.hawkbit.security; 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. * 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 { public class CoapAnonymousPreAuthenticatedFilter implements PreAuthenficationFilter {
@Override @Override
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) { public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecruityToken.COAP_TOKEN_VALUE); return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecurityToken.COAP_TOKEN_VALUE);
} }
@Override @Override
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) { public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecruityToken.COAP_TOKEN_VALUE); return new HeaderAuthentication(secruityToken.getControllerId(), TenantSecurityToken.COAP_TOKEN_VALUE);
} }
@Override @Override
public boolean isEnable(final TenantSecruityToken secruityToken) { public boolean isEnable(final TenantSecurityToken secruityToken) {
final String authHeader = secruityToken.getHeader(TenantSecruityToken.COAP_AUTHORIZATION_HEADER); final String authHeader = secruityToken.getHeader(TenantSecurityToken.COAP_AUTHORIZATION_HEADER);
return TenantSecruityToken.COAP_TOKEN_VALUE.equals(authHeader); return TenantSecurityToken.COAP_TOKEN_VALUE.equals(authHeader);
} }
} }

View File

@@ -8,7 +8,7 @@
*/ */
package org.eclipse.hawkbit.security; 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.SpPermission;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
@@ -67,8 +67,8 @@ public class ControllerPreAuthenticateSecurityTokenFilter extends AbstractContro
} }
@Override @Override
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) { public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
final String authHeader = secruityToken.getHeader(TenantSecruityToken.AUTHORIZATION_HEADER); final String authHeader = secruityToken.getHeader(TenantSecurityToken.AUTHORIZATION_HEADER);
if ((authHeader != null) && authHeader.startsWith(TARGET_SECURITY_TOKEN_AUTH_SCHEME)) { if ((authHeader != null) && authHeader.startsWith(TARGET_SECURITY_TOKEN_AUTH_SCHEME)) {
LOGGER.debug("found authorization header with scheme {} using target security token for authentication", LOGGER.debug("found authorization header with scheme {} using target security token for authentication",
TARGET_SECURITY_TOKEN_AUTH_SCHEME); TARGET_SECURITY_TOKEN_AUTH_SCHEME);
@@ -81,7 +81,7 @@ public class ControllerPreAuthenticateSecurityTokenFilter extends AbstractContro
} }
@Override @Override
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) { public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
final String securityToken = tenantAware.runAsTenant(secruityToken.getTenant(), final String securityToken = tenantAware.runAsTenant(secruityToken.getTenant(),
new GetSecurityTokenTenantRunner(secruityToken.getTenant(), secruityToken.getControllerId())); new GetSecurityTokenTenantRunner(secruityToken.getTenant(), secruityToken.getControllerId()));
return new HeaderAuthentication(secruityToken.getControllerId(), securityToken); return new HeaderAuthentication(secruityToken.getControllerId(), securityToken);

View File

@@ -8,7 +8,7 @@
*/ */
package org.eclipse.hawkbit.security; 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.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
@@ -56,8 +56,8 @@ public class ControllerPreAuthenticatedGatewaySecurityTokenFilter extends Abstra
} }
@Override @Override
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) { public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
final String authHeader = secruityToken.getHeader(TenantSecruityToken.AUTHORIZATION_HEADER); final String authHeader = secruityToken.getHeader(TenantSecurityToken.AUTHORIZATION_HEADER);
if ((authHeader != null) && authHeader.startsWith(GATEWAY_SECURITY_TOKEN_AUTH_SCHEME)) { if ((authHeader != null) && authHeader.startsWith(GATEWAY_SECURITY_TOKEN_AUTH_SCHEME)) {
LOGGER.debug("found authorization header with scheme {} using target security token for authentication", LOGGER.debug("found authorization header with scheme {} using target security token for authentication",
GATEWAY_SECURITY_TOKEN_AUTH_SCHEME); GATEWAY_SECURITY_TOKEN_AUTH_SCHEME);
@@ -71,7 +71,7 @@ public class ControllerPreAuthenticatedGatewaySecurityTokenFilter extends Abstra
} }
@Override @Override
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) { public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
final String gatewayToken = tenantAware.runAsTenant(secruityToken.getTenant(), final String gatewayToken = tenantAware.runAsTenant(secruityToken.getTenant(),
gatewaySecurityTokenKeyConfigRunner); gatewaySecurityTokenKeyConfigRunner);
return new HeaderAuthentication(secruityToken.getControllerId(), gatewayToken); return new HeaderAuthentication(secruityToken.getControllerId(), gatewayToken);

View File

@@ -8,7 +8,7 @@
*/ */
package org.eclipse.hawkbit.security; 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.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; 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 * An pre-authenticated processing filter which extracts the principal from a
* request URI and the credential from a request header in a the * 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 @Override
public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecruityToken secruityToken) { public HeaderAuthentication getPreAuthenticatedPrincipal(final TenantSecurityToken secruityToken) {
// retrieve the common name header and the authority name header from // retrieve the common name header and the authority name header from
// the http request and // the http request and
// combine them together // combine them together
@@ -97,7 +97,7 @@ public class ControllerPreAuthenticatedSecurityHeaderFilter extends AbstractCont
} }
@Override @Override
public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecruityToken secruityToken) { public HeaderAuthentication getPreAuthenticatedCredentials(final TenantSecurityToken secruityToken) {
final String authorityNameConfigurationValue = tenantAware.runAsTenant(secruityToken.getTenant(), final String authorityNameConfigurationValue = tenantAware.runAsTenant(secruityToken.getTenant(),
sslIssuerNameConfigTenantRunner); sslIssuerNameConfigTenantRunner);
String controllerId = secruityToken.getControllerId(); 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 * It's ok if we find the the hash in any the trusted CA chain to accept
* this request for this tenant. * 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. // iterate over the headers until we get a null header.
int iHeader = 1; int iHeader = 1;
String foundHash; String foundHash;

View File

@@ -8,7 +8,7 @@
*/ */
package org.eclipse.hawkbit.security; 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. * Interface for Pre Authenfication.
@@ -25,7 +25,7 @@ public interface PreAuthenficationFilter {
* the secruity info * the secruity info
* @return <true> is enabled <false> diabled * @return <true> is enabled <false> diabled
*/ */
boolean isEnable(TenantSecruityToken secruityToken); boolean isEnable(TenantSecurityToken secruityToken);
/** /**
* Extract the principal information from the current secruityToken. * Extract the principal information from the current secruityToken.
@@ -34,7 +34,7 @@ public interface PreAuthenficationFilter {
* the secruityToken * the secruityToken
* @return the extracted tenant and controller id * @return the extracted tenant and controller id
*/ */
HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecruityToken secruityToken); HeaderAuthentication getPreAuthenticatedPrincipal(TenantSecurityToken secruityToken);
/** /**
* Extract the principal credentials from the current secruityToken. * Extract the principal credentials from the current secruityToken.
@@ -43,6 +43,6 @@ public interface PreAuthenficationFilter {
* the secruityToken * the secruityToken
* @return the extracted tenant and controller id * @return the extracted tenant and controller id
*/ */
HeaderAuthentication getPreAuthenticatedCredentials(TenantSecruityToken secruityToken); HeaderAuthentication getPreAuthenticatedCredentials(TenantSecurityToken secruityToken);
} }