diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9bb86c1d681522176631e96aa83c1bfdd370f090..e4d81aedbff0bfe574964db1a86e6bd0ca6ed290 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
# 2.0.14
* [LGR-73](https://jira.software.geant.org/browse/LGR-73) - Remove router endpoint
+* [LGR-72](https://jira.software.geant.org/browse/LGR-72) - Check user is authenticated prior to executing commands on internal routers
# 2.0.13
* [LGR-70](https://jira.software.geant.org/browse/LGR-70) - Pull UI out of jar
diff --git a/pom.xml b/pom.xml
index 5652f0fb061e960d85468c929295018d46978d7f..cc4f764a2caf4d03b3d50d4f56dbdea038d657d4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -145,8 +145,7 @@
<line>After=syslog.target</line>
<line>[Service]</line>
<line>User=${artifactId}</line>
- <line>ExecStart=/opt/${artifactId}/latest/bin/${artifactId}.${project.packaging}
- --spring.config.location=file:/opt/${artifactId}/${version}/config/application.yml
+ <line>ExecStart=/opt/${artifactId}/latest/bin/${artifactId}.${project.packaging} --spring.config.location=file:/opt/${artifactId}/${version}/config/application.yml
</line>
<line>StandardOutput=syslog</line>
<line>StandardError=syslog</line>
diff --git a/src/main/java/org/geant/lgservice/LookingGlassServiceApplication.java b/src/main/java/org/geant/lgservice/LookingGlassServiceApplication.java
index 0e3e273e48f9f2339af39553b651762cd9cebcf5..8ed4c25017169ceaa4cb6fbac1c77f6d41c56f67 100644
--- a/src/main/java/org/geant/lgservice/LookingGlassServiceApplication.java
+++ b/src/main/java/org/geant/lgservice/LookingGlassServiceApplication.java
@@ -1,14 +1,15 @@
package org.geant.lgservice;
-import org.geant.lgservice.infrastructure.rest.inventoryprovider.Config;
+import org.geant.lgservice.infrastructure.rest.inventoryprovider.InventoryProviderConfig;
+import org.geant.lgservice.infrastructure.ssh.SSHConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
@SpringBootApplication
@Import({
- org.geant.lgservice.infrastructure.rest.inventoryprovider.Config.class,
- org.geant.lgservice.infrastructure.ssh.Config.class
+ InventoryProviderConfig.class,
+ SSHConfig.class
})
public class LookingGlassServiceApplication {
diff --git a/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/Config.java b/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/Config.java
deleted file mode 100644
index 46b88e30f924457baece8e105b0b605135286c7f..0000000000000000000000000000000000000000
--- a/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/Config.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.geant.lgservice.infrastructure.rest.inventoryprovider;
-
-import org.geant.lgservice.domain.RouterRepository;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class Config {
-
- @Bean
- public RouterRepository routerRepository(@Value("${inventoryprovider.baseUrl}")String baseUrl) {
- return InventoryProviderRouterRepository.builder().baseUrl(baseUrl).build();
- }
-
-}
diff --git a/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/InventoryProviderConfig.java b/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/InventoryProviderConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..81601df36f310ae51232bf8e3f27aee2c1bf3d59
--- /dev/null
+++ b/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/InventoryProviderConfig.java
@@ -0,0 +1,39 @@
+package org.geant.lgservice.infrastructure.rest.inventoryprovider;
+
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.geant.lgservice.domain.RouterRepository;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.io.IOException;
+
+@Configuration
+public class InventoryProviderConfig {
+
+ @Bean
+ public RouterRepository routerRepository(@Value("${inventoryprovider.baseUrl}")String baseUrl) {
+ return InventoryProviderRouterRepository.builder().baseUrl(baseUrl)
+ .client(new OkHttpClient.Builder().addInterceptor(new OkHttpLogger()).build()).build();
+ }
+
+ @Slf4j
+ private static class OkHttpLogger implements Interceptor {
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+
+ Request request = chain.request();
+ log.info("Making request to {} with headers {}", request.url().toString(), request.headers());
+ Response response = chain.proceed(request);
+ long contentLength = response.body().contentLength();
+ log.info("Response recieved with status {} and body {}", response.code(), response.peekBody(contentLength >= 0 ? contentLength : Long.MAX_VALUE).string());
+ return response;
+ }
+ }
+
+}
diff --git a/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/InventoryProviderRouterRepository.java b/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/InventoryProviderRouterRepository.java
index 7eabb49d91d965defbdb4268224a70fa74e37ba0..02003fac615c7070ee22e8bb99cf67f1915a5623 100644
--- a/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/InventoryProviderRouterRepository.java
+++ b/src/main/java/org/geant/lgservice/infrastructure/rest/inventoryprovider/InventoryProviderRouterRepository.java
@@ -7,7 +7,9 @@ import com.google.common.collect.ImmutableMap;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
+import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
+import okhttp3.Request;
import org.geant.lgservice.domain.Router;
import org.geant.lgservice.domain.RouterRepository;
import org.geant.lgservice.exceptions.TechnicalException;
@@ -23,8 +25,11 @@ import retrofit2.http.GET;
import java.io.IOException;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static java.nio.charset.Charset.defaultCharset;
import static org.geant.lgservice.domain.Router.Access.INTERNAL;
@@ -63,9 +68,22 @@ public class InventoryProviderRouterRepository implements RouterRepository {
@Builder
public InventoryProviderRouterRepository(String baseUrl, OkHttpClient client) {
+ OkHttpClient.Builder builder =
+ (client != null ? client.newBuilder() : new OkHttpClient.Builder());
+
+ List<Interceptor> existingInterceptors = builder.interceptors();
+ List<Interceptor> interceptors = Stream.concat(
+ Stream.of((Interceptor.Chain chain) -> chain.proceed(chain.request().newBuilder()
+ .addHeader("Accept", "application/json")
+ .build())),
+ existingInterceptors.stream()).collect(Collectors.toList());
+
+ existingInterceptors.removeIf(interceptors::contains);
+ existingInterceptors.addAll(interceptors);
+
this.inventoryProvider = new Retrofit.Builder()
.baseUrl(baseUrl)
- .client(client != null ? client : new OkHttpClient())
+ .client(builder.build())
.addConverterFactory(JacksonConverterFactory.create())
.build()
.create(InventoryProvider.class);
diff --git a/src/main/java/org/geant/lgservice/infrastructure/ssh/ConnectionFactory.java b/src/main/java/org/geant/lgservice/infrastructure/ssh/ConnectionFactory.java
index 46fa347a6f95c2d371f47333c158cf0b38a3e1ac..838cadc104ae218bcc523e36640f832a49e4b35a 100644
--- a/src/main/java/org/geant/lgservice/infrastructure/ssh/ConnectionFactory.java
+++ b/src/main/java/org/geant/lgservice/infrastructure/ssh/ConnectionFactory.java
@@ -30,7 +30,7 @@ public class ConnectionFactory {
} catch (IOException e) {
throw new TechnicalException(e);
}
- log.info("Connection for {} created");
+ log.info("Connection for {} created", hostname);
return connection;
}
}
diff --git a/src/main/java/org/geant/lgservice/infrastructure/ssh/ConnectionManager.java b/src/main/java/org/geant/lgservice/infrastructure/ssh/ConnectionManager.java
index 0f77845bb5a6a7ef01b37b5e2f26adb3f53d54f7..17f3249b21630c9213320fd606a08bf5db365fe7 100644
--- a/src/main/java/org/geant/lgservice/infrastructure/ssh/ConnectionManager.java
+++ b/src/main/java/org/geant/lgservice/infrastructure/ssh/ConnectionManager.java
@@ -8,6 +8,7 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.geant.lgservice.infrastructure.ssh.SSHHost.ConnectionStateListener.State.DISCONNECTED;
+import static org.geant.lgservice.infrastructure.ssh.SSHHost.ConnectionStateListener.State.ERROR;
@Slf4j
@Component
@@ -35,9 +36,11 @@ public class ConnectionManager implements SSHHost.ConnectionStateListener {
@Override
public void stateChanged(SSHHost host, State state) {
synchronized (this) {
- if (state.equals(DISCONNECTED)) {
+ log.info("host [{}] state changed to [{}]", host, state);
+ if (state.equals(DISCONNECTED) || state.equals(ERROR)) {
hosts.remove(host);
}
+ log.info("currently active connections: [{}]", hosts.keySet());
}
}
}
diff --git a/src/main/java/org/geant/lgservice/infrastructure/ssh/Config.java b/src/main/java/org/geant/lgservice/infrastructure/ssh/SSHConfig.java
similarity index 96%
rename from src/main/java/org/geant/lgservice/infrastructure/ssh/Config.java
rename to src/main/java/org/geant/lgservice/infrastructure/ssh/SSHConfig.java
index de7917939699e080eb5804697bf7296ce4318545..eb195bfd2a62db05ccab15b87e67ab81456dee63 100644
--- a/src/main/java/org/geant/lgservice/infrastructure/ssh/Config.java
+++ b/src/main/java/org/geant/lgservice/infrastructure/ssh/SSHConfig.java
@@ -7,7 +7,7 @@ import org.springframework.context.annotation.Configuration;
import java.io.File;
@Configuration
-public class Config {
+public class SSHConfig {
@Bean
public ConnectionFactory connectionFactory(
diff --git a/src/main/java/org/geant/lgservice/infrastructure/ssh/SSHHost.java b/src/main/java/org/geant/lgservice/infrastructure/ssh/SSHHost.java
index 8eba9473978cc53240b8b5a0b2ff08c198a9c688..98d7d29f0622cc5567c6671e31329d50f04f5099 100644
--- a/src/main/java/org/geant/lgservice/infrastructure/ssh/SSHHost.java
+++ b/src/main/java/org/geant/lgservice/infrastructure/ssh/SSHHost.java
@@ -12,10 +12,11 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Optional;
import java.util.stream.Collectors;
-import static ch.ethz.ssh2.ChannelCondition.EXIT_STATUS;
import static org.geant.lgservice.infrastructure.ssh.SSHHost.ConnectionStateListener.State.DISCONNECTED;
+import static org.geant.lgservice.infrastructure.ssh.SSHHost.ConnectionStateListener.State.ERROR;
@Slf4j
public class SSHHost implements ConnectionMonitor {
@@ -38,25 +39,25 @@ public class SSHHost implements ConnectionMonitor {
public String execute(String command) {
Session session = null;
try {
+ log.debug("opening session on connection [{}] with host [{}]", connection, hostname());
session = connection.openSession();
+ log.debug("Session [{}] opened", session);
log.debug("sending command [{}] to host [{}]", command, hostname());
session.execCommand(command);
+ log.debug("command [{}] sent to host [{}]", command, hostname());
- session.waitForCondition(EXIT_STATUS, 0);
- int exitStatus = session.getExitStatus();
+ int exitStatus = Optional.of(session).map(Session::getExitStatus).orElse(0);
log.debug("Exit status [{}] recieved", exitStatus);
- InputStream response = exitStatus == 0 ? session.getStdout() : session.getStderr();
+ InputStream response = exitStatus != 0 ? session.getStderr() : session.getStdout();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(response))) {
return reader.lines().collect(Collectors.joining("\n"));
}
} catch (IOException e) {
+ triggerStateChangeListeners(ERROR);
+ connection.close();
throw new TechnicalException(e);
- } finally {
- if (session != null) {
- session.close();
- }
}
}
@@ -69,18 +70,23 @@ public class SSHHost implements ConnectionMonitor {
return this;
}
+ private void triggerStateChangeListeners(ConnectionStateListener.State state) {
+ connectionStateListeners
+ .forEach(connectionStateListener -> connectionStateListener.stateChanged(this, state));
+ }
+
@Override
public void connectionLost(Throwable reason) {
log.warn("Host [{}] lost connection: ", connection.getHostname(), reason);
- connectionStateListeners
- .forEach(connectionStateListener -> connectionStateListener.stateChanged(this, DISCONNECTED));
+ triggerStateChangeListeners(DISCONNECTED);
}
@FunctionalInterface
public interface ConnectionStateListener {
enum State {
- DISCONNECTED
+ DISCONNECTED,
+ ERROR
}
void stateChanged(SSHHost host, State state);
diff --git a/src/main/java/org/geant/lgservice/interfaces/rest/BusinessExceptionHandler.java b/src/main/java/org/geant/lgservice/interfaces/rest/BusinessExceptionHandler.java
index a67f39942644af7bbedf38e2b830558a1d79af68..07fb9acb6696f814d69616b33ffbe63ca2f36836 100644
--- a/src/main/java/org/geant/lgservice/interfaces/rest/BusinessExceptionHandler.java
+++ b/src/main/java/org/geant/lgservice/interfaces/rest/BusinessExceptionHandler.java
@@ -1,5 +1,6 @@
package org.geant.lgservice.interfaces.rest;
+import lombok.extern.slf4j.Slf4j;
import org.geant.lgservice.exceptions.BusinessException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -7,13 +8,13 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
+@Slf4j
@ControllerAdvice
public class BusinessExceptionHandler extends ResponseEntityExceptionHandler {
-
-
@ExceptionHandler(BusinessException.class)
protected ResponseEntity<Object> handleBusinessException (BusinessException ex) {
+ log.info("Business error: {}", ex.getMessage());
return ResponseEntity.status(HttpStatus.valueOf(ex.getReason().name())).build();
}
}
diff --git a/src/main/java/org/geant/lgservice/pojos/Command.java b/src/main/java/org/geant/lgservice/pojos/Command.java
index 265d84425583960b6155ec275484ea4a2cc02a3e..d6f806f2a0d077cc887b5c16070d8406d05ab566 100644
--- a/src/main/java/org/geant/lgservice/pojos/Command.java
+++ b/src/main/java/org/geant/lgservice/pojos/Command.java
@@ -6,11 +6,11 @@ import lombok.Setter;
@NoArgsConstructor
@Setter
+@Getter
public class Command {
private String name;
- @Getter
private String value;
private String description;