Skip to content
This repository has been archived by the owner on Jul 26, 2022. It is now read-only.

Commit

Permalink
Authentication with CLI to daemon
Browse files Browse the repository at this point in the history
  • Loading branch information
pimotte committed Aug 4, 2014
1 parent 27bd83f commit 2b42bc0
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 29 deletions.
39 changes: 28 additions & 11 deletions syncany-cli/src/main/java/org/syncany/cli/CommandLineClient.java
Expand Up @@ -19,9 +19,7 @@

import static java.util.Arrays.asList;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
Expand All @@ -44,25 +42,29 @@
import joptsimple.OptionSet;
import joptsimple.OptionSpec;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.simpleframework.xml.core.Persister;
import org.syncany.Client;
import org.syncany.config.Config;
import org.syncany.config.ConfigException;
import org.syncany.config.ConfigHelper;
import org.syncany.config.LogFormatter;
import org.syncany.config.Logging;
import org.syncany.config.to.PortTO;
import org.syncany.operations.daemon.messages.CliRequest;
import org.syncany.operations.daemon.messages.CliResponse;
import org.syncany.operations.daemon.messages.MessageFactory;
import org.syncany.operations.daemon.messages.Response;
import org.syncany.util.EnvironmentUtil;
import org.syncany.util.FileUtil;

/**
* The command line client implements a typical CLI. It represents the first entry
Expand All @@ -76,7 +78,7 @@ public class CommandLineClient extends Client {

private static final String SERVER_PROTOCOL = "http://";
private static final String SERVER_HOSTNAME = "localhost";
private static int SERVER_PORT = 8080;
private static PortTO portTO;
private static final String SERVER_REST_API = "/api/rs";

private static final String LOG_FILE_PATTERN = "syncany.log";
Expand Down Expand Up @@ -315,12 +317,11 @@ private int runCommand(Command command, String commandName, String[] commandArgs
boolean sendToRest = localDirHandledInDaemonScope && needsToRunInInitializedScope;

if (sendToRest) {
try (BufferedReader portFileReader = new BufferedReader(new FileReader(portFile))) {
SERVER_PORT = Integer.parseInt(portFileReader.readLine());
try {
portTO = new Persister().read(PortTO.class, portFile);
}
catch (Exception e) {
logger.log(Level.SEVERE, "Cannot read REST server port from: " + portFile + ", because: " + e.getMessage());
SERVER_PORT = 8080;
logger.log(Level.SEVERE, "ERROR: Could not read portFile to connect to daemon.", e);
}
return sendToRest(command, commandName, commandArgs);
}
Expand All @@ -345,9 +346,25 @@ private int runLocally(Command command, String[] commandArgs) {
}

private int sendToRest(Command command, String commandName, String[] commandArgs) {
CloseableHttpClient client = HttpClients.createDefault();
if (portTO == null) {
logger.log(Level.SEVERE, "No port information available");
return showErrorAndExit("Cannot connect to daemon.");
}


// Create authentication details
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(SERVER_HOSTNAME, portTO.getPort()),
new UsernamePasswordCredentials(portTO.getUser().getUsername(), portTO.getUser().getPassword()));

// Create client with authentication details
CloseableHttpClient client = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider)
.build();


String SERVER_URI = SERVER_PROTOCOL + SERVER_HOSTNAME + ":" + SERVER_PORT + SERVER_REST_API;
String SERVER_URI = SERVER_PROTOCOL + SERVER_HOSTNAME + ":" + portTO.getPort() + SERVER_REST_API;
HttpPost post = new HttpPost(SERVER_URI);

try {
Expand Down
Expand Up @@ -39,6 +39,9 @@ public class DaemonConfigTO {
@ElementList(name = "users", entry = "user", required = false)
private ArrayList<UserTO> users = new ArrayList<UserTO>();

// This is not in xml on purpose. It is generated dynamically by the daemon.
private PortTO portTO;

public static DaemonConfigTO load(File file) throws ConfigException {
try {
return new Persister().read(DaemonConfigTO.class, file);
Expand Down Expand Up @@ -80,4 +83,12 @@ public WebServerTO getWebServer() {
public void setWebServer(WebServerTO webServer) {
this.webServer = webServer;
}

public PortTO getPortTO() {
return portTO;
}

public void setPortTO(PortTO portTO) {
this.portTO = portTO;
}
}
Expand Up @@ -28,6 +28,7 @@
import org.syncany.config.UserConfig;
import org.syncany.config.to.DaemonConfigTO;
import org.syncany.config.to.FolderTO;
import org.syncany.config.to.PortTO;
import org.syncany.config.to.UserTO;
import org.syncany.crypto.CipherUtil;
import org.syncany.operations.Operation;
Expand Down Expand Up @@ -77,6 +78,7 @@ public class DaemonOperation extends Operation {
private ControlServer controlServer;
private LocalEventBus eventBus;
private DaemonConfigTO daemonConfig;
private PortTO portTO;

public DaemonOperation(Config config) {
super(config);
Expand Down Expand Up @@ -160,6 +162,18 @@ private void loadOrCreateConfig() {
else {
daemonConfig = createAndWriteDefaultConfig(daemonConfigFile);
}

if (portTO == null) {
// Add user and password for access from the CLI
String accessToken = CipherUtil.createRandomAlphanumericString(20);
UserTO cliUser = new UserTO();
cliUser.setUsername("CLI");
cliUser.setPassword(accessToken);
portTO = new PortTO();
portTO.setPort(daemonConfig.getWebServer().getPort());
portTO.setUser(cliUser);
daemonConfig.setPortTO(portTO);
}
}
catch (Exception e) {
logger.log(Level.WARNING, "Cannot (re-)load config. Exception thrown.", e);
Expand Down
Expand Up @@ -30,11 +30,13 @@
import java.util.logging.Level;
import java.util.logging.Logger;

import org.simpleframework.xml.core.Persister;
import org.syncany.Client;
import org.syncany.cli.Command;
import org.syncany.cli.CommandFactory;
import org.syncany.config.Config;
import org.syncany.config.ConfigException;
import org.syncany.config.to.PortTO;
import org.syncany.database.ChunkEntry.ChunkChecksum;
import org.syncany.database.DatabaseVersionHeader;
import org.syncany.database.FileContent;
Expand Down Expand Up @@ -86,18 +88,18 @@ public class WatchRunner implements WatchOperationListener {

private Config config;
private File portFile;
private int port;
private PortTO portTO;
private Thread watchThread;
private WatchOperation watchOperation;
private WatchOperationResult watchOperationResult;
private LocalEventBus eventBus;

private SqlDatabase localDatabase;

public WatchRunner(Config config, WatchOperationOptions watchOperationOptions, int port) throws ConfigException {
public WatchRunner(Config config, WatchOperationOptions watchOperationOptions, PortTO portTO) throws ConfigException {
this.config = config;
this.portFile = new File(config.getAppDir(), Config.FILE_PORT);
this.port = port;
this.portTO = portTO;
this.watchOperation = new WatchOperation(config, watchOperationOptions, this);

this.localDatabase = new SqlDatabase(config);
Expand All @@ -116,14 +118,7 @@ public void run() {

// Write port to portFile
portFile.createNewFile();
try (FileWriter portFileWriter = new FileWriter(portFile)) {
String portStr = Integer.toString(port);

logger.log(Level.INFO, "Writing Port file (for Port " + portStr + ") to " + portFile + " ...");

portFileWriter.write(portStr);
portFileWriter.close();
}
new Persister().write(portTO, portFile);
portFile.deleteOnExit();

// Start operation
Expand Down
Expand Up @@ -21,7 +21,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand All @@ -31,6 +30,7 @@
import org.syncany.config.ConfigHelper;
import org.syncany.config.to.DaemonConfigTO;
import org.syncany.config.to.FolderTO;
import org.syncany.config.to.PortTO;
import org.syncany.operations.daemon.messages.BadRequestResponse;
import org.syncany.operations.daemon.messages.ListWatchesRequest;
import org.syncany.operations.daemon.messages.ListWatchesResponse;
Expand All @@ -55,7 +55,7 @@ public class WatchServer {

private Map<File, WatchRunner> watchOperations;
private LocalEventBus eventBus;
private int port;
private PortTO portTO;

public WatchServer() {
this.watchOperations = new TreeMap<File, WatchRunner>();
Expand All @@ -72,7 +72,7 @@ public void reload(DaemonConfigTO daemonConfigTO) {
logger.log(Level.INFO, "Starting/reloading watch server ... ");

// Update port number
port = daemonConfigTO.getWebServer().getPort();
portTO = daemonConfigTO.getPortTO();

// Restart threads
try {
Expand Down Expand Up @@ -114,7 +114,7 @@ private void startWatchOperations(Map<File, FolderTO> newWatchedFolderTOs) throw
if (watchConfig != null) {
logger.log(Level.INFO, "- Starting watch operation at " + localDir + " ...");

WatchRunner watchOperationThread = new WatchRunner(watchConfig, watchOperationOptions, port);
WatchRunner watchOperationThread = new WatchRunner(watchConfig, watchOperationOptions, portTO);
watchOperationThread.start();

watchOperations.put(localDir, watchOperationThread);
Expand Down
Expand Up @@ -44,6 +44,7 @@

import org.syncany.config.to.DaemonConfigTO;
import org.syncany.config.to.UserTO;
import org.syncany.crypto.CipherUtil;
import org.syncany.operations.daemon.auth.MapIdentityManager;
import org.syncany.operations.daemon.handlers.InternalRestHandler;
import org.syncany.operations.daemon.handlers.InternalWebInterfaceHandler;
Expand Down Expand Up @@ -83,7 +84,7 @@ public WebServer(DaemonConfigTO daemonConfig) {

initCaches();
initEventBus();
initServer(daemonConfig.getWebServer().getHost(), daemonConfig.getWebServer().getPort(), daemonConfig.getUsers());
initServer(daemonConfig);
}

public void start() throws ServiceAlreadyStartedException {
Expand Down Expand Up @@ -116,12 +117,22 @@ private void initEventBus() {
eventBus.register(this);
}

private void initServer(String host, int port, List<UserTO> users) {
private void initServer(DaemonConfigTO daemonConfigTO) {
String host = daemonConfigTO.getWebServer().getHost();
int port = daemonConfigTO.getWebServer().getPort();
List<UserTO> users = daemonConfigTO.getUsers();

if (users == null) {
users = new ArrayList<UserTO>();
logger.log(Level.WARNING, "Webserver is starting without any users. No access possible.");
}

if (daemonConfigTO.getPortTO() != null) {
// Add CLI credentials
users.add(daemonConfigTO.getPortTO().getUser());
}



IdentityManager identityManager = new MapIdentityManager(users);

HttpHandler pathHttpHandler = path()
Expand Down

0 comments on commit 2b42bc0

Please sign in to comment.