Started migration for Boot 1.3 and Security 4.1

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
kaizimmerm
2016-07-07 12:39:40 +02:00
parent b3db6e4ae2
commit ff500d3bd7
25 changed files with 265 additions and 878 deletions

View File

@@ -26,7 +26,7 @@
<logger name="server-security" level="INFO" /> <logger name="server-security" level="INFO" />
<Root level="INFO"> <Root level="INFO">
<AppenderRef ref="Console" /> <appender-ref ref="CONSOLE" />
</Root> </Root>
</configuration> </configuration>

View File

@@ -14,8 +14,8 @@
<logger name="feign.Logger" level="debug" /> <logger name="feign.Logger" level="debug" />
<root level="INFO"> <Root level="INFO">
<appender-ref ref="STDOUT" /> <appender-ref ref="CONSOLE" />
</root> </Root>
</configuration> </configuration>

View File

@@ -11,14 +11,12 @@ package org.eclipse.hawkbit.artifact.repository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/** /**
* Auto configuration for the {@link ArtifactStore}. * Auto configuration for the {@link ArtifactStore}.
*/ */
@Configuration @Configuration
@ConditionalOnMissingBean(value = ArtifactRepository.class) @ConditionalOnMissingBean(value = ArtifactRepository.class)
@Import(value = MongoConfiguration.class)
public class ArtifactStoreAutoConfiguration { public class ArtifactStoreAutoConfiguration {
/** /**

View File

@@ -1,119 +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.artifact.repository;
import java.net.UnknownHostException;
import java.util.Arrays;
import javax.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoClientOptions.Builder;
import com.mongodb.MongoClientURI;
import com.mongodb.ServerAddress;
/**
* {@link AbstractMongoConfiguration} that uses {@link MongoClientURI} even when
* port is configured for NON {@link Cloud} use cases.
*
*/
@Configuration
@EnableConfigurationProperties(MongoProperties.class)
@ConditionalOnClass(Mongo.class)
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
@Profile({ "!cloud" })
public class MongoConfiguration extends AbstractMongoConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(MongoConfiguration.class);
@Autowired
private MongoProperties properties;
@Autowired(required = false)
private MongoClientOptions options;
private Mongo mongoConnection;
@Override
public String getDatabaseName() {
return properties.getMongoClientDatabase();
}
/**
* Closes mongo client when destroyed.
*/
@PreDestroy
public void close() {
if (this.mongoConnection != null) {
this.mongoConnection.close();
}
}
@Override
@Bean
@ConditionalOnMissingBean
// Closed by pre-destroy
@SuppressWarnings({ "squid:S2095" })
public Mongo mongo() throws UnknownHostException {
final MongoClientURI uri = new MongoClientURI(properties.getUri(), createBuilderOutOfOptions(options));
if (properties.getPort() != null) {
LOG.debug("Create mongo by properties (host: {}, port: {})", uri.getHosts().get(0), properties.getPort());
this.mongoConnection = new MongoClient(
Arrays.asList(new ServerAddress(uri.getHosts().get(0), properties.getPort())), uri.getOptions());
} else {
LOG.debug("Create mongo by URI : {}", uri);
this.mongoConnection = new MongoClient(uri);
}
return this.mongoConnection;
}
/*
* Creates {@link MongoClientOptions} builder out of existing options as the
* {@link MongoClientURI} expects a builder.
*
* Based on MongoProperties#builder method.
*/
private static Builder createBuilderOutOfOptions(final MongoClientOptions options) {
final Builder builder = MongoClientOptions.builder();
if (options != null) {
builder.alwaysUseMBeans(options.isAlwaysUseMBeans());
builder.connectionsPerHost(options.getConnectionsPerHost());
builder.connectTimeout(options.getConnectTimeout());
builder.cursorFinalizerEnabled(options.isCursorFinalizerEnabled());
builder.dbDecoderFactory(options.getDbDecoderFactory());
builder.dbEncoderFactory(options.getDbEncoderFactory());
builder.description(options.getDescription());
builder.maxWaitTime(options.getMaxWaitTime());
builder.readPreference(options.getReadPreference());
builder.serverSelectionTimeout(options.getServerSelectionTimeout());
builder.socketFactory(options.getSocketFactory());
builder.socketKeepAlive(options.isSocketKeepAlive());
builder.socketTimeout(options.getSocketTimeout());
builder.threadsAllowedToBlockForConnectionMultiplier(
options.getThreadsAllowedToBlockForConnectionMultiplier());
builder.writeConcern(options.getWriteConcern());
}
return builder;
}
}

View File

@@ -1,78 +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.artifact;
import java.io.File;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import org.apache.commons.io.IOUtils;
/**
*
* Look for a free port.
*/
public class FreePortFileWriter {
private final String filePortPath;
private final int from;
private final int to;
/**
* @param from
* port range from (start point)
* @param to
* port range to (end point)
*/
public FreePortFileWriter(final int from, final int to, final String filePortPath) {
this.from = from;
this.to = to;
this.filePortPath = filePortPath;
}
public int getPort() {
return findFree();
}
protected int findFree() {
for (int i = from; i <= to; i++) {
if (isFree(i)) {
return i;
}
}
throw new RuntimeException("No free port in range " + from + ":" + to);
}
boolean isFree(final int port) {
ServerSocket sock = null;
try {
final File portFile = new File(filePortPath + File.separator + port + ".port");
portFile.getParentFile().mkdirs();
if (portFile.exists()) {
return false;
}
boolean isFree = false;
sock = new ServerSocket();
sock.setReuseAddress(true);
sock.bind(new InetSocketAddress(port));
if (portFile.createNewFile()) {
portFile.deleteOnExit();
isFree = true;
}
return isFree;
// We rely on an exception thrown to determine availability or
// not availability and don't want to log the exception.
} catch (@SuppressWarnings({ "squid:S2221", "squid:S1166" }) final Exception e) {
return false;
} finally {
IOUtils.closeQuietly(sock);
}
}
}

View File

@@ -1,115 +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.artifact;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.UUID;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.flapdoodle.embed.mongo.Command;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.ArtifactStoreBuilder;
import de.flapdoodle.embed.mongo.config.DownloadConfigBuilder;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.config.store.HttpProxyFactory;
import de.flapdoodle.embed.process.runtime.Network;
/**
*
*
*/
public class MongoDBTestRule implements TestRule {
private static final Logger LOG = LoggerFactory.getLogger(MongoDBTestRule.class);
private static volatile MongodExecutable mongodExecutable = null;
private static volatile MongodProcess mongod;
private final String id = UUID.randomUUID().toString();
@Override
public Statement apply(final Statement base, final Description description) {
return statement(base, description);
}
private Statement statement(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
before(base, description);
try {
base.evaluate();
} finally {
after();
}
}
};
}
private void after() {
if (mongodExecutable != null) {
LOG.info("Stop MongoDB...");
mongodExecutable.stop();
mongodExecutable = null;
if (mongod != null) {
mongod.stop();
mongod = null;
}
LOG.info("MongoDB stopped... {}", id);
}
}
private void before(final Statement base, final Description description) throws UnknownHostException, IOException {
final Command command = Command.MongoD;
final RuntimeConfigBuilder runtimeConfig = new RuntimeConfigBuilder().defaults(command);
int port = -1;
if (System.getProperty("spring.data.mongodb.port") != null) {
port = Integer.parseInt(System.getProperty("spring.data.mongodb.port"));
} else {
port = new FreePortFileWriter(27017, 27100, "./target/freeports").getPort();
System.setProperty("spring.data.mongodb.port", String.valueOf(port));
}
Version version = Version.V3_0_8;
if (System.getProperty("inf.mongodb.version") != null) {
version = Version.valueOf("V" + System.getProperty("inf.mongodb.version").trim().replaceAll("\\.", "_"));
}
if (System.getProperty("http.proxyHost") != null) {
runtimeConfig.artifactStore(new ArtifactStoreBuilder().defaults(command)
.download(new DownloadConfigBuilder().defaultsForCommand(command)
.proxyFactory(new HttpProxyFactory(System.getProperty("http.proxyHost").trim(),
Integer.valueOf(System.getProperty("http.proxyPort"))))));
}
final IMongodConfig mongodConfig = new MongodConfigBuilder().version(version)
.net(new Net("127.0.0.1", port, Network.localhostIsIPv6())).build();
final MongodStarter starter = MongodStarter.getInstance(runtimeConfig.build());
mongodExecutable = starter.prepare(mongodConfig);
LOG.info("Start MongoDB...");
mongod = mongodExecutable.start();
final Net net = mongod.getConfig().net();
LOG.info("MongoDB started id {} on bind ip :{} Port:{} and version {}", id, net.getBindIp(), net.getPort(),
mongodConfig.version().toString());
}
}

View File

@@ -18,10 +18,8 @@ import java.security.NoSuchAlgorithmException;
import java.util.Random; import java.util.Random;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.eclipse.hawkbit.artifact.MongoDBTestRule;
import org.eclipse.hawkbit.artifact.TestConfiguration; import org.eclipse.hawkbit.artifact.TestConfiguration;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.junit.ClassRule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -29,6 +27,7 @@ import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsOperations; import org.springframework.data.mongodb.gridfs.GridFsOperations;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.google.common.io.BaseEncoding; import com.google.common.io.BaseEncoding;
@@ -42,11 +41,9 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Stories("Artifact Store MongoDB") @Stories("Artifact Store MongoDB")
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { ArtifactStoreAutoConfiguration.class, TestConfiguration.class }) @SpringApplicationConfiguration(classes = { ArtifactStoreAutoConfiguration.class, TestConfiguration.class })
@TestPropertySource(properties = { "spring.data.mongodb.port=0", "spring.mongodb.embedded.version=3.2.7" })
public class ArtifactStoreTest { public class ArtifactStoreTest {
@ClassRule
public static final MongoDBTestRule mongoDBRule = new MongoDBTestRule();
@Autowired @Autowired
private ArtifactStore artifactStoreUnderTest; private ArtifactStore artifactStoreUnderTest;

View File

@@ -13,7 +13,6 @@ import static org.springframework.context.annotation.AdviceMode.ASPECTJ;
import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.servlet.Filter; import javax.servlet.Filter;
@@ -22,7 +21,6 @@ import javax.servlet.FilterConfig;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter; import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter;
import org.eclipse.hawkbit.cache.CacheConstants; import org.eclipse.hawkbit.cache.CacheConstants;
@@ -69,7 +67,6 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
@@ -80,9 +77,6 @@ import org.springframework.security.web.authentication.LoginUrlAuthenticationEnt
import org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter; import org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
import org.springframework.security.web.session.HttpSessionEventPublisher; import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.security.web.session.SessionManagementFilter; import org.springframework.security.web.session.SessionManagementFilter;
import org.vaadin.spring.security.VaadinSecurityContext; import org.vaadin.spring.security.VaadinSecurityContext;
@@ -99,7 +93,6 @@ import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSucc
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = ASPECTJ, proxyTargetClass = true, securedEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true, mode = ASPECTJ, proxyTargetClass = true, securedEnabled = true)
@EnableWebMvcSecurity
@Order(value = HIGHEST_PRECEDENCE) @Order(value = HIGHEST_PRECEDENCE)
public class SecurityManagedConfiguration { public class SecurityManagedConfiguration {
@@ -191,9 +184,7 @@ public class SecurityManagedConfiguration {
controllerAnonymousDownloadFilter.setCheckForPrincipalChanges(true); controllerAnonymousDownloadFilter.setCheckForPrincipalChanges(true);
controllerAnonymousDownloadFilter.setAuthenticationDetailsSource(authenticationDetailsSource); controllerAnonymousDownloadFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
HttpSecurity httpSec = http.csrf().disable().headers() HttpSecurity httpSec = http.csrf().disable();
.addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.DENY)).contentTypeOptions()
.xssProtection().httpStrictTransportSecurity().and();
if (springSecurityProperties.isRequireSsl()) { if (springSecurityProperties.isRequireSsl()) {
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and(); httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
@@ -342,20 +333,12 @@ public class SecurityManagedConfiguration {
@Order(400) @Order(400)
@EnableVaadinSecurity @EnableVaadinSecurity
public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private static final String XFRAME_OPTION_DENY = "DENY";
private static final String XFRAME_OPTION_SAMEORIGIN = "SAMEORIGIN";
private static final String XFAME_OPTION_ALLOW_FROM = "ALLOW-FROM";
@Autowired @Autowired
private VaadinSecurityContext vaadinSecurityContext; private VaadinSecurityContext vaadinSecurityContext;
@Autowired @Autowired
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties; private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
@Autowired
private HawkbitSecurityProperties securityProperties;
/** /**
* post construct for setting the authentication success handler for the * post construct for setting the authentication success handler for the
* vaadin security context. * vaadin security context.
@@ -409,18 +392,6 @@ public class SecurityManagedConfiguration {
@Override @Override
protected void configure(final HttpSecurity http) throws Exception { protected void configure(final HttpSecurity http) throws Exception {
// configuration xframe-option
final String confXframeOption = securityProperties.getXframe().getOption();
final String confAllowFromUri = securityProperties.getXframe().getAllowfrom();
if (XFAME_OPTION_ALLOW_FROM.equals(confXframeOption) && confAllowFromUri.isEmpty()) {
// if allow-from option is specified but no allowFromUri throw
// exception
throw new IllegalStateException("hawkbit.server.security.xframe.option has been specified as ALLOW-FROM"
+ " but no hawkbit.server.security.xframe.allowfrom has been set, "
+ "please ensure to set allow from URIs");
}
// workaround regex: we need to exclude the URL /UI/HEARTBEAT here // workaround regex: we need to exclude the URL /UI/HEARTBEAT here
// because we bound the vaadin application to /UI and not to root, // because we bound the vaadin application to /UI and not to root,
// described in vaadin-forum: // described in vaadin-forum:
@@ -437,12 +408,7 @@ public class SecurityManagedConfiguration {
"\"******************\\n** Requires HTTPS Security has been disabled for UI, should only be used for developing purposes **\\n******************\""); "\"******************\\n** Requires HTTPS Security has been disabled for UI, should only be used for developing purposes **\\n******************\"");
} }
// for UI integrator we allow frame integration on same origin httpSec
httpSec.headers()
.addHeaderWriter(confXframeOption.equals(XFAME_OPTION_ALLOW_FROM)
? new XFrameOptionsHeaderWriter(new StaticAllowFromStrategy(new URI(confAllowFromUri)))
: new XFrameOptionsHeaderWriter(xframeOptionFromStr(confXframeOption)))
.contentTypeOptions().xssProtection().httpStrictTransportSecurity().and()
// UI // UI
.authorizeRequests().antMatchers("/UI/login/**").permitAll().antMatchers("/UI/UIDL/**").permitAll() .authorizeRequests().antMatchers("/UI/login/**").permitAll().antMatchers("/UI/UIDL/**").permitAll()
.anyRequest().authenticated().and() .anyRequest().authenticated().and()
@@ -451,29 +417,6 @@ public class SecurityManagedConfiguration {
.and().logout().logoutUrl("/UI/logout").logoutSuccessUrl("/UI/login/#/"); .and().logout().logoutUrl("/UI/logout").logoutSuccessUrl("/UI/login/#/");
} }
/**
* Converts a given string into the {@link XFrameOptionsMode} enum. Only
* {@link XFrameOptionsMode#DENY} and
* {@link XFrameOptionsMode#SAMEORIGIN} any other string will be
* converted to the default {@link XFrameOptionsMode#SAMEORIGIN}.
*
* @param xframeOption
* the string of the xframe option
* @return an {@link XFrameOptionsMode} by the given string, in case
* string does not match an option then
* {@link XFrameOptionsMode#SAMEORIGIN} is returned
*/
private static XFrameOptionsMode xframeOptionFromStr(@NotNull final String xframeOption) {
switch (xframeOption) {
case XFRAME_OPTION_DENY:
return XFrameOptionsMode.DENY;
case XFRAME_OPTION_SAMEORIGIN:
// fall through to default because the same
default:
return XFrameOptionsMode.SAMEORIGIN;
}
}
@Override @Override
public void configure(final WebSecurity webSecurity) throws Exception { public void configure(final WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/documentation/**", "/VAADIN/**", "/*.*", "/v2/api-docs/**", webSecurity.ignoring().antMatchers("/documentation/**", "/VAADIN/**", "/*.*", "/v2/api-docs/**",

View File

@@ -21,12 +21,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.TimeZone;
import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.RandomUtils;
import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent; import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
@@ -35,6 +38,7 @@ import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.test.util.WithUser; import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB; import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -59,15 +63,18 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Stories("Artifact Download Resource") @Stories("Artifact Download Resource")
public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB { public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB {
private static final int ARTIFACT_SIZE = 5 * 1024 * 1024;
public DdiArtifactDownloadTest() { public DdiArtifactDownloadTest() {
LOG = LoggerFactory.getLogger(DdiArtifactDownloadTest.class); LOG = LoggerFactory.getLogger(DdiArtifactDownloadTest.class);
} }
private volatile int downLoadProgress = 0; private volatile int downLoadProgress = 0;
private volatile long shippedBytes = 0;
private volatile long shippedBytesTotal = 0; private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
@Before
public void setup() {
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
}
@Autowired @Autowired
private EventBus eventBus; private EventBus eventBus;
@@ -240,8 +247,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
@Description("Tests valid downloads through the artifact resource by identifying the artifact not by ID but file name.") @Description("Tests valid downloads through the artifact resource by identifying the artifact not by ID but file name.")
public void downloadArtifactThroughFileName() throws Exception { public void downloadArtifactThroughFileName() throws Exception {
downLoadProgress = 1; downLoadProgress = 1;
shippedBytes = 0;
shippedBytesTotal = 0;
eventBus.register(this); eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
@@ -255,7 +260,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact // create artifact
final byte random[] = RandomUtils.nextBytes(ARTIFACT_SIZE); final byte random[] = RandomUtils.nextBytes(5 * 1024 * 1024);
final LocalArtifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), final LocalArtifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).getId(), "file1", false); ds.findFirstModuleByType(osType).getId(), "file1", false);
@@ -273,7 +278,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
ds.findFirstModuleByType(osType).getId(), artifact.getFilename())) ds.findFirstModuleByType(osType).getId(), artifact.getFilename()))
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().longValue("Last-Modified", artifact.getCreatedAt())) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().string("Content-Disposition", "attachment;filename=" + artifact.getFilename())) .andExpect(header().string("Content-Disposition", "attachment;filename=" + artifact.getFilename()))
.andReturn(); .andReturn();
@@ -282,7 +287,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
// download complete // download complete
assertThat(downLoadProgress).isEqualTo(10); assertThat(downLoadProgress).isEqualTo(10);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(ARTIFACT_SIZE);
} }
@Test @Test
@@ -320,8 +324,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
+ "anonymous as authorization is notpossible, e.g. chekc if the controller has the artifact assigned.") + "anonymous as authorization is notpossible, e.g. chekc if the controller has the artifact assigned.")
public void downloadArtifactByNameFailsIfNotAuthenticated() throws Exception { public void downloadArtifactByNameFailsIfNotAuthenticated() throws Exception {
downLoadProgress = 1; downLoadProgress = 1;
shippedBytes = 0;
shippedBytesTotal = 0;
eventBus.register(this); eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
@@ -329,24 +331,21 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
// create target // create target
Target target = entityFactory.generateTarget("4712"); Target target = entityFactory.generateTarget("4712");
target = targetManagement.createTarget(target); target = targetManagement.createTarget(target);
final List<Target> targets = new ArrayList<>(); final List<Target> targets = new ArrayList();
targets.add(target); targets.add(target);
// create ds // create ds
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact // create artifact
final byte random[] = RandomUtils.nextBytes(ARTIFACT_SIZE); final byte random[] = RandomUtils.nextBytes(5 * 1024);
artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), final Artifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).getId(), "file1.tar.bz2", false); ds.findFirstModuleByType(osType).getId(), "file1.tar.bz2", false);
// download fails as artifact is not yet assigned to target // download fails as artifact is not yet assigned to target
deploymentManagement.assignDistributionSet(ds, targets); deploymentManagement.assignDistributionSet(ds, targets);
mvc.perform(get("/controller/artifacts/v1/filename/{filename}", "file1.tar.bz2")) mvc.perform(get("/controller/artifacts/v1/filename/{filename}", "file1.tar.bz2"))
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
assertThat(downLoadProgress).isEqualTo(1);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(0L);
} }
@Test @Test
@@ -354,8 +353,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
@Description("Ensures that an authenticated and named controller is permitted to download.") @Description("Ensures that an authenticated and named controller is permitted to download.")
public void downloadArtifactByNameByNamedController() throws Exception { public void downloadArtifactByNameByNamedController() throws Exception {
downLoadProgress = 1; downLoadProgress = 1;
shippedBytes = 0;
shippedBytesTotal = 0;
eventBus.register(this); eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
@@ -370,7 +367,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact // create artifact
final byte random[] = RandomUtils.nextBytes(ARTIFACT_SIZE); final byte random[] = RandomUtils.nextBytes(5 * 1024 * 1024);
final Artifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), final Artifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).getId(), "file1", false); ds.findFirstModuleByType(osType).getId(), "file1", false);
@@ -386,7 +383,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
.andExpect(status().isOk()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isOk()).andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().longValue("Last-Modified", artifact.getCreatedAt())) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn(); .andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
assertTrue("The same file that was uploaded is expected when downloaded", assertTrue("The same file that was uploaded is expected when downloaded",
@@ -403,7 +400,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
// download complete // download complete
assertThat(downLoadProgress).isEqualTo(10); assertThat(downLoadProgress).isEqualTo(10);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(ARTIFACT_SIZE);
} }
@Test @Test
@@ -444,7 +440,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().longValue("Last-Modified", artifact.getCreatedAt())) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().longValue("Content-Length", range)) .andExpect(header().longValue("Content-Length", range))
.andExpect(header().string("Content-Range", "bytes " + rangeString + "/" + resultLength)) .andExpect(header().string("Content-Range", "bytes " + rangeString + "/" + resultLength))
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn(); .andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
@@ -461,7 +457,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().longValue("Last-Modified", artifact.getCreatedAt())) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().longValue("Content-Length", 1000)) .andExpect(header().longValue("Content-Length", 1000))
.andExpect(header().string("Content-Range", .andExpect(header().string("Content-Range",
"bytes " + (resultLength - 1000) + "-" + (resultLength - 1) + "/" + resultLength)) "bytes " + (resultLength - 1000) + "-" + (resultLength - 1) + "/" + resultLength))
@@ -477,7 +473,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().longValue("Last-Modified", artifact.getCreatedAt())) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().longValue("Content-Length", resultLength - 1000)) .andExpect(header().longValue("Content-Length", resultLength - 1000))
.andExpect(header().string("Content-Range", .andExpect(header().string("Content-Range",
"bytes " + 1000 + "-" + (resultLength - 1) + "/" + resultLength)) "bytes " + 1000 + "-" + (resultLength - 1) + "/" + resultLength))
@@ -493,7 +489,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType("multipart/byteranges; boundary=THIS_STRING_SEPARATES_MULTIPART")) .andExpect(content().contentType("multipart/byteranges; boundary=THIS_STRING_SEPARATES_MULTIPART"))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().longValue("Last-Modified", artifact.getCreatedAt())) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn(); .andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
outputStream.reset(); outputStream.reset();
@@ -565,8 +561,5 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
@Subscribe @Subscribe
public void listen(final DownloadProgressEvent event) { public void listen(final DownloadProgressEvent event) {
downLoadProgress++; downLoadProgress++;
shippedBytes += event.getShippedBytesSinceLast();
shippedBytesTotal = event.getShippedBytesOverall();
} }
} }

View File

@@ -12,10 +12,10 @@
<configuration> <configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" /> <include resource="org/springframework/boot/logging/logback/base.xml" />
<!-- <Logger name="org.eclipse.hawkbit.rest.util.MockMvcResultPrinter" level="DEBUG" /> --> <Logger name="org.eclipse.hawkbit.rest.util.MockMvcResultPrinter" level="DEBUG" />
<Root level="INFO"> <Root level="INFO">
<AppenderRef ref="Console" /> <appender-ref ref="CONSOLE" />
</Root> </Root>
</configuration> </configuration>

View File

@@ -29,7 +29,7 @@
<logger name="server-security" level="INFO" /> <logger name="server-security" level="INFO" />
<Root level="INFO"> <Root level="INFO">
<AppenderRef ref="Console" /> <appender-ref ref="CONSOLE" />
</Root> </Root>
</configuration> </configuration>

View File

@@ -115,7 +115,7 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac
@Override @Override
protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response, protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response,
final Authentication authResult) { final Authentication authResult) throws IOException, ServletException {
final Collection<GrantedAuthority> authorities = new ArrayList<>(); final Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.addAll(authResult.getAuthorities()); authorities.addAll(authResult.getAuthorities());
authorities.addAll(abstractControllerAuthenticationFilter.getSuccessfulAuthenticationAuthorities()); authorities.addAll(abstractControllerAuthenticationFilter.getSuccessfulAuthenticationAuthorities());

View File

@@ -15,10 +15,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest; import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.junit.BeforeClass; import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
@@ -34,23 +34,17 @@ import ru.yandex.qatools.allure.annotations.Stories;
*/ */
@Features("Component Tests - Management API") @Features("Component Tests - Management API")
@Stories("Download Resource") @Stories("Download Resource")
public class SMRessourceMisingMongoDbConnectionTest extends AbstractRestIntegrationTest { public class SMRessourceMisingMongoDbConnectionTest extends AbstractRestIntegrationTestWithMongoDB {
@BeforeClass
public static void initialize() {
// set property to mongoPort which does not start any mongoDB of
// parallel test execution
System.setProperty("spring.data.mongodb.port", "1020");
}
@Test @Test
@Description("Ensures that the correct error code is returned in case MongoDB unavailable.") @Description("Ensures that the correct error code is returned in case MongoDB unavailable.")
public void missingMongoDbConnectionResultsInErrorAtUpload() throws Exception { public void missingMongoDbConnectionResultsInErrorAtUpload() throws Exception {
mongodExecutable.stop();
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
assertThat(artifactManagement.countLocalArtifactsAll()).isEqualTo(0); assertThat(artifactManagement.countLocalArtifactsAll()).isEqualTo(0);
SoftwareModule sm = entityFactory.generateSoftwareModule( SoftwareModule sm = entityFactory.generateSoftwareModule(softwareManagement.findSoftwareModuleTypeByKey("os"),
softwareManagement.findSoftwareModuleTypeByKey("os"), "name 1", "version 1", null, null); "name 1", "version 1", null, null);
sm = softwareManagement.createSoftwareModule(sm); sm = softwareManagement.createSoftwareModule(sm);
assertThat(artifactManagement.countLocalArtifactsAll()).isEqualTo(0); assertThat(artifactManagement.countLocalArtifactsAll()).isEqualTo(0);
@@ -74,4 +68,9 @@ public class SMRessourceMisingMongoDbConnectionTest extends AbstractRestIntegrat
} }
@After
public void cleanCurrentCollection() {
// not needed, mongodb is stopped already
}
} }

View File

@@ -29,7 +29,7 @@
<logger name="server-security" level="INFO" /> <logger name="server-security" level="INFO" />
<Root level="INFO"> <Root level="INFO">
<AppenderRef ref="Console" /> <appender-ref ref="CONSOLE" />
</Root> </Root>
</configuration> </configuration>

View File

@@ -0,0 +1,74 @@
/**
* 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.repository.jpa;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.net.UnknownHostException;
import org.eclipse.hawkbit.repository.exception.ArtifactDeleteFailedException;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.junit.After;
import org.junit.Test;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
@Features("Component Tests - Repository")
@Stories("Artifact Management")
public class ArtifactManagementFailedMongoDBTest extends AbstractJpaIntegrationTestWithMongoDB {
@Test
@Description("Trys and fails to delete or create local artifact with a down mongodb and checks if expected ArtifactDeleteFailedException is thrown.")
public void deleteArtifactsWithNoMongoDb() throws UnknownHostException, IOException {
// ensure baseline
assertThat(artifactRepository.findAll()).isEmpty();
// prepare test
JpaSoftwareModule sm = new JpaSoftwareModule(softwareManagement.findSoftwareModuleTypeByKey("os"), "name 1",
"version 1", null, null);
sm = softwareModuleRepository.save(sm);
final Artifact result = artifactManagement.createLocalArtifact(new RandomGeneratedInputStream(5 * 1024),
sm.getId(), "file1", false);
assertThat(artifactRepository.findAll()).hasSize(1);
mongodExecutable.stop();
try {
artifactManagement.deleteLocalArtifact(result.getId());
fail("deletion should have failed");
} catch (final ArtifactDeleteFailedException e) {
}
try {
artifactManagement.createLocalArtifact(new RandomGeneratedInputStream(5 * 1024), sm.getId(), "file2",
false);
fail("Should not have worked with MongoDb down.");
} catch (final ArtifactUploadFailedException e) {
}
assertThat(artifactRepository.findAll()).hasSize(1);
}
@Override
@After
public void cleanCurrentCollection() {
// no need to clean, is stopped already
}
}

View File

@@ -1,58 +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.repository.jpa;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.junit.BeforeClass;
import org.junit.Test;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
/**
* Addition tests next to {@link ArtifactManagementTest} with no running MongoDB
*
*/
@Features("Component Tests - Repository")
@Stories("Artifact Management")
public class ArtifactManagementNoMongoDbTest extends AbstractJpaIntegrationTest {
@BeforeClass
public static void initialize() {
// set property to mongoPort which does not start any mongoDB of
// parallel test execution
System.setProperty("spring.data.mongodb.port", "1020");
}
@Test
@Description("Checks if the expected ArtifactUploadFailedException is thrown in case of MongoDB down")
public void createLocalArtifactWithMongoDbDown() throws IOException {
JpaSoftwareModule sm = new JpaSoftwareModule(softwareManagement.findSoftwareModuleTypeByKey("os"), "name 1",
"version 1", null, null);
sm = softwareModuleRepository.save(sm);
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
try {
artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), sm.getId(), "file1", false);
fail("Should not have worked with MongoDb down.");
} catch (final ArtifactUploadFailedException e) {
}
}
}

View File

@@ -15,14 +15,12 @@ import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.exception.ArtifactDeleteFailedException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.model.JpaExternalArtifact; import org.eclipse.hawkbit.repository.jpa.model.JpaExternalArtifact;
import org.eclipse.hawkbit.repository.jpa.model.JpaExternalArtifactProvider; import org.eclipse.hawkbit.repository.jpa.model.JpaExternalArtifactProvider;
@@ -241,36 +239,6 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTestWithMongoD
assertThat(artifactRepository.findAll()).hasSize(0); assertThat(artifactRepository.findAll()).hasSize(0);
} }
@Test
@Description("Trys and fails to delete local artifact with a down mongodb and checks if expected ArtifactDeleteFailedException is thrown.")
public void deleteArtifactsWithNoMongoDb() throws UnknownHostException, IOException {
// ensure baseline
assertThat(artifactRepository.findAll()).isEmpty();
// prepare test
JpaSoftwareModule sm = new JpaSoftwareModule(softwareManagement.findSoftwareModuleTypeByKey("os"), "name 1",
"version 1", null, null);
sm = softwareModuleRepository.save(sm);
final Artifact result = artifactManagement.createLocalArtifact(new RandomGeneratedInputStream(5 * 1024),
sm.getId(), "file1", false);
assertThat(artifactRepository.findAll()).hasSize(1);
internalShutDownMongo();
try {
artifactManagement.deleteLocalArtifact(result.getId());
fail("deletion should have failed");
} catch (final ArtifactDeleteFailedException e) {
}
setupMongo();
assertThat(artifactRepository.findAll()).hasSize(1);
assertThat(artifactManagement.findArtifact(result.getId())).isEqualTo(result);
}
@Test @Test
@Description("Test the deletion of an artifact metadata where the binary is still linked to another " @Description("Test the deletion of an artifact metadata where the binary is still linked to another "
+ "metadata element. The expected result is that the metadata is deleted but the binary kept.") + "metadata element. The expected result is that the metadata is deleted but the binary kept.")

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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
-->
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<Root level="INFO">
<appender-ref ref="CONSOLE" />
</Root>
</configuration>

View File

@@ -51,6 +51,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
@@ -68,6 +69,7 @@ import org.springframework.web.context.WebApplicationContext;
// refreshed we e.g. get two instances of CacheManager which leads to very // refreshed we e.g. get two instances of CacheManager which leads to very
// strange test failures. // strange test failures.
@DirtiesContext(classMode = ClassMode.AFTER_CLASS) @DirtiesContext(classMode = ClassMode.AFTER_CLASS)
@TestPropertySource(properties = { "spring.data.mongodb.port=0", "spring.mongodb.embedded.version=3.2.7" })
public abstract class AbstractIntegrationTest implements EnvironmentAware { public abstract class AbstractIntegrationTest implements EnvironmentAware {
protected static Logger LOG = null; protected static Logger LOG = null;

View File

@@ -8,103 +8,27 @@
*/ */
package org.eclipse.hawkbit.repository.test.util; package org.eclipse.hawkbit.repository.test.util;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsOperations; import org.springframework.data.mongodb.gridfs.GridFsOperations;
import de.flapdoodle.embed.mongo.Command;
import de.flapdoodle.embed.mongo.MongodExecutable; import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.ArtifactStoreBuilder;
import de.flapdoodle.embed.mongo.config.DownloadConfigBuilder;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.config.store.HttpProxyFactory;
import de.flapdoodle.embed.process.runtime.Network;
/** /**
* Test class that contains MonfoDb start and stop for the test * Test class that contains embedded MongoDB for the test.
*
*
*
*
*/ */
public abstract class AbstractIntegrationTestWithMongoDB extends AbstractIntegrationTest { public abstract class AbstractIntegrationTestWithMongoDB extends AbstractIntegrationTest {
protected static volatile MongodExecutable mongodExecutable = null;
private static final AtomicInteger mongoLease = new AtomicInteger(0);
private static volatile Integer port;
@Autowired @Autowired
protected GridFsOperations operations; protected GridFsOperations operations;
@BeforeClass @Autowired
public static void setupMongo() throws UnknownHostException, IOException { protected MongodExecutable mongodExecutable;
mongoLease.incrementAndGet();
if (mongodExecutable == null) {
final Command command = Command.MongoD;
final RuntimeConfigBuilder runtimeConfig = new RuntimeConfigBuilder().defaults(command);
if (port == null) {
port = new FreePortFileWriter(28017, 28090, "./target/freeports").getPort();
System.setProperty("spring.data.mongodb.port", String.valueOf(port));
}
Version version = Version.V3_0_8;
if (System.getProperty("inf.mongodb.version") != null) {
version = Version
.valueOf("V" + System.getProperty("inf.mongodb.version").trim().replaceAll("\\.", "_"));
}
if (System.getProperty("http.proxyHost") != null) {
runtimeConfig
.artifactStore(
new ArtifactStoreBuilder().defaults(command)
.download(new DownloadConfigBuilder().defaultsForCommand(command)
.proxyFactory(new HttpProxyFactory(
System.getProperty("http.proxyHost").trim(), Integer
.valueOf(System.getProperty("http.proxyPort"))))));
}
final IMongodConfig mongodConfig = new MongodConfigBuilder().version(version)
.net(new Net("127.0.0.1", port, Network.localhostIsIPv6())).build();
final MongodStarter starter = MongodStarter.getInstance(runtimeConfig.build());
mongodExecutable = starter.prepare(mongodConfig);
mongodExecutable.start();
}
}
@After @After
public void cleanCurrentCollection() { public void cleanCurrentCollection() {
operations.delete(new Query()); operations.delete(new Query());
} }
public static void internalShutDownMongo() {
if (mongodExecutable != null && mongoLease.decrementAndGet() <= 0) {
mongodExecutable.stop();
mongodExecutable = null;
}
}
@AfterClass
public static void shutdownMongo() throws UnknownHostException, IOException {
if (mongodExecutable != null && mongoLease.decrementAndGet() <= 0) {
mongodExecutable.stop();
mongodExecutable = null;
}
port = null;
}
} }

View File

@@ -1,73 +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.repository.test.util;
import java.io.File;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
/**
*
* Look for a free port.
*/
public class FreePortFileWriter {
private final String filePortPath;
private final int from;
private final int to;
/**
* @param from
* port range from (start point)
* @param to
* port range to (end point)
*/
public FreePortFileWriter(final int from, final int to, final String filePortPath) {
this.from = from;
this.to = to;
this.filePortPath = filePortPath;
}
public int getPort() {
return findFree();
}
protected int findFree() {
for (int i = from; i <= to; i++) {
if (isFree(i)) {
return i;
}
}
throw new RuntimeException("No free port in range " + from + ":" + to);
}
boolean isFree(final int port) {
try {
final File portFile = new File(filePortPath + File.separator + port + ".port");
portFile.getParentFile().mkdirs();
if (portFile.exists()) {
return false;
}
boolean isFree = false;
final ServerSocket sock = new ServerSocket();
sock.setReuseAddress(true);
sock.bind(new InetSocketAddress(port));
if (portFile.createNewFile()) {
portFile.deleteOnExit();
isFree = true;
}
sock.close();
return isFree;
// We rely on an exception thrown to determine availability or
// not availability and don't want to log the exception.
} catch (@SuppressWarnings({ "squid:S2221", "squid:S1166" }) final Exception e) {
return false;
}
}
}

View File

@@ -45,11 +45,10 @@ import com.mongodb.MongoClientOptions;
* *
*/ */
@Configuration @Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.PROXY, proxyTargetClass = false, securedEnabled = true)
@EnableConfigurationProperties({ HawkbitServerProperties.class, DdiSecurityProperties.class }) @EnableConfigurationProperties({ HawkbitServerProperties.class, DdiSecurityProperties.class })
@Profile("test") @Profile("test")
public class TestConfiguration implements AsyncConfigurer { public class TestConfiguration implements AsyncConfigurer {
@Bean @Bean
public TestRepositoryManagement testRepositoryManagement() { public TestRepositoryManagement testRepositoryManagement() {
return new JpaTestRepositoryManagement(); return new JpaTestRepositoryManagement();

View File

@@ -185,22 +185,18 @@ public final class SpPermission {
field.setAccessible(true); field.setAccessible(true);
try { try {
final String role = (String) field.get(null); final String role = (String) field.get(null);
addIfNotExcluded(exclusionRoles, allPermissions, role); if (!(exclusionRoles.contains(role))) {
allPermissions.add(role);
}
} catch (final IllegalAccessException e) { } catch (final IllegalAccessException e) {
LOGGER.error(e.getMessage(), e); LOGGER.error(e.getMessage(), e);
} }
} }
} }
return allPermissions; return allPermissions;
} }
private static void addIfNotExcluded(final Collection<String> exclusionRoles, final List<String> allPermissions,
final String role) {
if (!(exclusionRoles.contains(role))) {
allPermissions.add(role);
}
}
/** /**
* Contains all the spring security evaluation expressions for the * Contains all the spring security evaluation expressions for the
* {@link PreAuthorize} annotation for method security. * {@link PreAuthorize} annotation for method security.
@@ -228,10 +224,8 @@ public final class SpPermission {
/* /*
* Spring security eval expressions. * Spring security eval expressions.
*/ */
private static final String BRACKET_OPEN = "("; private static final String HAS_AUTH_PREFIX = "hasAuthority('";
private static final String BRACKET_CLOSE = ")"; private static final String HAS_AUTH_SUFFIX = "')";
private static final String HAS_AUTH_PREFIX = "hasAuthority" + BRACKET_OPEN + "'";
private static final String HAS_AUTH_SUFFIX = "'" + BRACKET_CLOSE;
private static final String HAS_AUTH_AND = " and "; private static final String HAS_AUTH_AND = " and ";
/** /**
@@ -263,6 +257,99 @@ public final class SpPermission {
*/ */
public static final String HAS_AUTH_OR = " or "; public static final String HAS_AUTH_OR = " or ";
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_TARGET}.
*/
public static final String HAS_AUTH_UPDATE_TARGET = HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#SYSTEM_ADMIN}.
*/
public static final String HAS_AUTH_SYSTEM_ADMIN = HAS_AUTH_PREFIX + SYSTEM_ADMIN + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET}.
*/
public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_TARGET}.
*/
public static final String HAS_AUTH_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_TARGET}.
*/
public static final String HAS_AUTH_DELETE_TARGET = HAS_AUTH_PREFIX + DELETE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#UPDATE_TARGET}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = HAS_AUTH_PREFIX + READ_REPOSITORY
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + CREATE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_REPOSITORY}.
*/
public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + DELETE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY}.
*/
public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + READ_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_REPOSITORY}.
*/
public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + UPDATE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#READ_TARGET}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET = HAS_AUTH_PREFIX + READ_REPOSITORY
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DOWNLOAD_REPOSITORY_ARTIFACT}.
*/
public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + DOWNLOAD_REPOSITORY_ARTIFACT
+ HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAnyRole expression to check if the spring
* context contains the anoynmous role or the controller specific role
* {@link SpPermission#CONTROLLER_ROLE}.
*/
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
+ "')";
/**
* Spring security eval hasAuthority expression to check if the spring
* context contains the role to allow controllers to download specific
* role {@link SpPermission#CONTROLLER_DOWNLOAD_ROLE}.
*/
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
+ HAS_AUTH_SUFFIX;
/** /**
* Spring security eval hasAnyRole expression to check if the spring * Spring security eval hasAnyRole expression to check if the spring
* context contains system code role * context contains system code role
@@ -272,176 +359,47 @@ public final class SpPermission {
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_TARGET} or * context contains {@link SpPermission#CREATE_REPOSITORY} and
* {@link #IS_SYSTEM_CODE}. * {@link SpPermission#CREATE_TARGET}.
*/ */
public static final String HAS_AUTH_UPDATE_TARGET = HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX public static final String HAS_AUTH_CREATE_REPOSITORY_AND_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_REPOSITORY
+ HAS_AUTH_OR + IS_SYSTEM_CODE; + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#SYSTEM_ADMIN} or * context contains {@link SpPermission#ROLLOUT_MANAGEMENT}
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_SYSTEM_ADMIN = HAS_AUTH_PREFIX + SYSTEM_ADMIN + HAS_AUTH_SUFFIX public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX + HAS_AUTH_OR
+ IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET_SEC_TOKEN} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_TARGET_SEC_TOKEN = HAS_AUTH_PREFIX + READ_TARGET_SEC_TOKEN
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DELETE_TARGET = HAS_AUTH_PREFIX + DELETE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#UPDATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + CREATE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + DELETE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + READ_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + UPDATE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#READ_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DOWNLOAD_REPOSITORY_ARTIFACT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + DOWNLOAD_REPOSITORY_ARTIFACT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAnyRole expression to check if the spring
* context contains the anoynmous role or the controller specific role
* {@link SpringEvalExpressions#CONTROLLER_ROLE}.
*/
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
+ "')";
/**
* Spring security eval hasAuthority expression to check if the spring
* context contains the role to allow controllers to download specific
* role {@link SpringEvalExpressions#CONTROLLER_DOWNLOAD_ROLE}
*/
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
+ HAS_AUTH_SUFFIX; + HAS_AUTH_SUFFIX;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} and * context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and
* {@link SpPermission#CREATE_TARGET} or {@link #IS_SYSTEM_CODE}. * {@link SpPermission#READ_TARGET}
*/ */
public static final String HAS_AUTH_CREATE_REPOSITORY_AND_CREATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ = HAS_AUTH_PREFIX
+ CREATE_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX + ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX;
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and * context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and
* {@link SpPermission#READ_TARGET} or {@link #IS_SYSTEM_CODE}. * {@link SpPermission#UPDATE_TARGET}.
*/ */
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ = BRACKET_OPEN + HAS_AUTH_PREFIX public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT
+ ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX;
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and * context contains {@link SpPermission#TENANT_CONFIGURATION}
* {@link SpPermission#UPDATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE = BRACKET_OPEN + HAS_AUTH_PREFIX
+ ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET
+ HAS_AUTH_SUFFIX + BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#TENANT_CONFIGURATION} or
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE; + HAS_AUTH_SUFFIX;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#SYSTEM_MONITOR} or * context contains {@link SpPermission#SYSTEM_MONITOR}
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_SYSTEM_MONITOR = HAS_AUTH_PREFIX + SYSTEM_MONITOR + HAS_AUTH_SUFFIX public static final String HAS_AUTH_SYSTEM_MONITOR = HAS_AUTH_PREFIX + SYSTEM_MONITOR + HAS_AUTH_SUFFIX;
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
private SpringEvalExpressions() { private SpringEvalExpressions() {
// utility class // utility class

View File

@@ -21,7 +21,6 @@ public class HawkbitSecurityProperties {
private final Clients clients = new Clients(); private final Clients clients = new Clients();
private final Dos dos = new Dos(); private final Dos dos = new Dos();
private final Xframe xframe = new Xframe();
public Dos getDos() { public Dos getDos() {
return dos; return dos;
@@ -31,45 +30,6 @@ public class HawkbitSecurityProperties {
return clients; return clients;
} }
public Xframe getXframe() {
return xframe;
}
/**
* Defines the XFrameOption policy.
*
*/
public static class Xframe {
/**
* XFrame option. Allowed values: SAMEORIGIN, DENY, ALLOW-FROM
*/
private String option = "DENY";
/**
* ALLOW-FROM defined URL, has to be filled in case ALLOW-FROM option is
* selected.
*/
private String allowfrom = "";
public String getOption() {
return option;
}
public void setOption(final String option) {
this.option = option;
}
public String getAllowfrom() {
return allowfrom;
}
public void setAllowfrom(final String allowfrom) {
this.allowfrom = allowfrom;
}
}
/** /**
* Security configuration related to clients. * Security configuration related to clients.
* *

10
pom.xml
View File

@@ -14,7 +14,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.8.RELEASE</version> <version>1.3.6.RELEASE</version>
</parent> </parent>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.eclipse.hawkbit</groupId>
@@ -61,17 +61,13 @@
<properties> <properties>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<spring.boot.version>1.2.8.RELEASE</spring.boot.version> <spring.boot.version>1.3.6.RELEASE</spring.boot.version>
<!-- Spring boot version overrides (should be reviewed with every boot upgrade) - START --> <!-- Spring boot version overrides (should be reviewed with every boot upgrade) - START -->
<!-- Newer versions needed than defined in Boot--> <!-- Newer versions needed than defined in Boot-->
<jackson.version>2.5.5</jackson.version>
<hibernate-validator.version>5.2.4.Final</hibernate-validator.version>
<spring-cloud-connectors.version>1.2.0.RELEASE</spring-cloud-connectors.version> <spring-cloud-connectors.version>1.2.0.RELEASE</spring-cloud-connectors.version>
<spring-amqp.version>1.6.1.RELEASE</spring-amqp.version> <spring-amqp.version>1.6.1.RELEASE</spring-amqp.version>
<spring-hateoas.version>0.18.0.RELEASE</spring-hateoas.version>
<!-- Support for MongoDB 3 --> <!-- Support for MongoDB 3 -->
<spring-data-releasetrain.version>Fowler-SR1</spring-data-releasetrain.version>
<mongodb.version>3.2.2</mongodb.version> <mongodb.version>3.2.2</mongodb.version>
<!-- Spring boot version overrides - END --> <!-- Spring boot version overrides - END -->
@@ -102,7 +98,7 @@
<json-path.version>0.9.1</json-path.version> <json-path.version>0.9.1</json-path.version>
<guava.version>19.0</guava.version> <guava.version>19.0</guava.version>
<mariadb-java-client.version>1.4.3</mariadb-java-client.version> <mariadb-java-client.version>1.4.3</mariadb-java-client.version>
<embedded-mongo.version>1.50.2</embedded-mongo.version> <embedded-mongo.version>1.50.5</embedded-mongo.version>
<jersey-client.version>1.18.1</jersey-client.version> <jersey-client.version>1.18.1</jersey-client.version>
<javax.el-api.version>2.2.4</javax.el-api.version> <javax.el-api.version>2.2.4</javax.el-api.version>
<corn-cps.version>1.1.7</corn-cps.version> <corn-cps.version>1.1.7</corn-cps.version>