From cdac7185c47dc9c8b9288d669a89d57950cf0548 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 23 Mar 2016 10:23:35 +0100 Subject: [PATCH] fix typo of class TenantSecurityToken and handle authentication message based on FileResource not only on SHA1 hash Signed-off-by: Michael Hirsch --- .../amqp/AmqpControllerAuthentfication.java | 6 +- .../amqp/AmqpMessageHandlerService.java | 52 ++++-- .../AmqpControllerAuthenticationTest.java | 29 +-- .../amqp/AmqpMessageHandlerServiceTest.java | 9 +- .../dmf/json/model/TenantSecruityToken.java | 94 ---------- .../dmf/json/model/TenantSecurityToken.java | 176 ++++++++++++++++++ ...actHttpControllerAuthenticationFilter.java | 15 +- .../repository/ArtifactManagement.java | 3 +- ...bstractControllerAuthenticationFilter.java | 8 +- .../CoapAnonymousPreAuthenticatedFilter.java | 16 +- ...lerPreAuthenticateSecurityTokenFilter.java | 8 +- ...thenticatedGatewaySecurityTokenFilter.java | 8 +- ...rPreAuthenticatedSecurityHeaderFilter.java | 10 +- .../security/PreAuthenficationFilter.java | 8 +- 14 files changed, 279 insertions(+), 163 deletions(-) delete mode 100644 hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecruityToken.java create mode 100644 hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecurityToken.java diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java index 8f19d9f02..3fa7979b9 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java @@ -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; diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java index cfd5485a6..71b8f8db8 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java @@ -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()); diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java index 66527727a..d7ab805ed 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java @@ -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); diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java index 9d6ae3ba7..930ca02ad 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java @@ -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); diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecruityToken.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecruityToken.java deleted file mode 100644 index 351684f5e..000000000 --- a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecruityToken.java +++ /dev/null @@ -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 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 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 headers) { - this.headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - this.headers.putAll(headers); - } - -} diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecurityToken.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecurityToken.java new file mode 100644 index 000000000..9e07d3fc4 --- /dev/null +++ b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecurityToken.java @@ -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 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 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 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 + "]"; + } + } +} diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java index adb2858b9..ace5bc834 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java @@ -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 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; } diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java index a5ee019dc..122d7b881 100644 --- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ArtifactManagement.java @@ -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; diff --git a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/AbstractControllerAuthenticationFilter.java b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/AbstractControllerAuthenticationFilter.java index d22c432cf..9a1cd2aea 100644 --- a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/AbstractControllerAuthenticationFilter.java +++ b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/AbstractControllerAuthenticationFilter.java @@ -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 { @Override diff --git a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/CoapAnonymousPreAuthenticatedFilter.java b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/CoapAnonymousPreAuthenticatedFilter.java index d9d8b9fa7..36a444c43 100644 --- a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/CoapAnonymousPreAuthenticatedFilter.java +++ b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/CoapAnonymousPreAuthenticatedFilter.java @@ -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); } } diff --git a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticateSecurityTokenFilter.java b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticateSecurityTokenFilter.java index c30f60711..8ff1e9ebc 100644 --- a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticateSecurityTokenFilter.java +++ b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticateSecurityTokenFilter.java @@ -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); diff --git a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedGatewaySecurityTokenFilter.java b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedGatewaySecurityTokenFilter.java index 765589df4..7d1bd7b0f 100644 --- a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedGatewaySecurityTokenFilter.java +++ b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedGatewaySecurityTokenFilter.java @@ -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); diff --git a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedSecurityHeaderFilter.java b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedSecurityHeaderFilter.java index ef8b5fbf7..6836b8a31 100644 --- a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedSecurityHeaderFilter.java +++ b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/ControllerPreAuthenticatedSecurityHeaderFilter.java @@ -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; diff --git a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/PreAuthenficationFilter.java b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/PreAuthenficationFilter.java index 8aa957005..8981fa9af 100644 --- a/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/PreAuthenficationFilter.java +++ b/hawkbit-security-integration/src/main/java/org/eclipse/hawkbit/security/PreAuthenficationFilter.java @@ -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 is enabled 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); }