Started migration for Boot 1.3 and Security 4.1
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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/**",
|
||||||
|
|||||||
@@ -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();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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());
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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.")
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
10
pom.xml
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user