Commit ac1de47a authored by zeroleak's avatar zeroleak
Browse files

add cli.api.port=8899 + cli.api.http-port=8898 + cli.api.http-enable=false

parent 932d26ec
# whirlpool-client-cli API
## Using REST API
whirlpool-client-cli exposes a REST API over HTTPS when started with --listen.
HTTPS port is defined in `whirlpool-cli-config.properties`:
```
cli.api.port-https=8899
cli.api.port=8899
```
HTTPS requirement can be disabled at your own risk:
Clear HTTP can be enabled at your own risk:
```
cli.api.require-https=false
cli.api.port-http=8898
cli.api.http-enable=true
cli.api.http-port=8898
```
......
......@@ -23,7 +23,7 @@ java -jar target/whirlpool-client-version-run.jar
```
Optional arguments:
- ```--listen[=8899]```: enable API for remote commands & GUI. Authentication on startup is optional, but you can authenticate on startup with --authenticate
- ```--listen```: enable API for remote commands & GUI. Authentication on startup is optional, but you can authenticate on startup with --authenticate
- ```--mixs-target```: minimum number of mixs to achieve per UTXO
- ```--authenticate```: will ask for your passphrase at startup
- ```--list-pools```: list pools and exit
......
......@@ -27,7 +27,7 @@ import org.springframework.core.env.Environment;
public class Application implements ApplicationRunner {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static Integer listenPort;
private static boolean listen;
private static boolean debug;
private static boolean debugClient;
private static ConfigurableApplicationContext applicationContext;
......@@ -45,10 +45,7 @@ public class Application implements ApplicationRunner {
"classpath:application.properties,./" + CliConfigService.CLI_CONFIG_FILENAME);
// start REST api if --listen
listenPort = ApplicationArgs.getMainListen(args);
if (listenPort != null) {
System.setProperty("server.port", Integer.toString(listenPort));
}
listen = ApplicationArgs.getMainListen(args);
// enable debug logs with --debug
debug = ApplicationArgs.isMainDebug(args);
......@@ -56,8 +53,7 @@ public class Application implements ApplicationRunner {
CliUtils.setLogLevel(debug, debugClient);
// run
WebApplicationType wat =
listenPort != null ? WebApplicationType.SERVLET : WebApplicationType.NONE;
WebApplicationType wat = listen ? WebApplicationType.SERVLET : WebApplicationType.NONE;
applicationContext =
new SpringApplicationBuilder(Application.class)
.logStartupInfo(debugClient)
......@@ -101,11 +97,10 @@ public class Application implements ApplicationRunner {
log.debug("Run... " + Arrays.toString(applicationArguments.getSourceArgs()));
}
boolean listen = (listenPort != null);
if (log.isDebugEnabled()) {
log.debug("[cli/debug] debug=" + debug + ", debugClient=" + debugClient);
log.debug("[cli/protocolVersion] " + WhirlpoolProtocol.PROTOCOL_VERSION);
log.debug("[cli/listen] " + (listen ? listenPort : "false"));
log.debug("[cli/listen] " + listen);
}
try {
......@@ -160,8 +155,4 @@ public class Application implements ApplicationRunner {
.filter(a -> !a.toLowerCase().equals("--" + ApplicationArgs.ARG_INIT))
.toArray(i -> new String[i]);
}
public static Integer getListenPort() {
return listenPort;
}
}
......@@ -15,7 +15,6 @@ import org.springframework.stereotype.Service;
@Service
public class ApplicationArgs {
private Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private static final int LISTEN_DEFAULT_PORT = 8899;
private static final String ARG_DEBUG = "debug";
private static final String ARG_DEBUG_CLIENT = "debug-client";
......@@ -126,8 +125,8 @@ public class ApplicationArgs {
return args.containsOption(ARG_AUTHENTICATE);
}
public static Integer getMainListen(String[] mainArgs) {
return mainInteger(ARG_LISTEN, mainArgs, null, LISTEN_DEFAULT_PORT);
public static boolean getMainListen(String[] mainArgs) {
return mainBoolean(ARG_LISTEN, mainArgs);
}
public static boolean isMainDebug(String[] mainArgs) {
......
......@@ -31,7 +31,7 @@ public class ApiCliConfig {
private static final String KEY_MIX_TX0_MAX_OUTPUTS = "cli.mix.tx0MaxOutputs";
private static final String KEY_MIX_AUTO_MIX = "cli.mix.autoMix";
private static final String KEY_MIX_MIXS_TARGET = "cli.mix.mixsTarget";
public static final String KEY_API_REQUIRE_HTTPS = "cli.api.require-https";
public static final String KEY_API_HTTP_ENABLE = "cli.api.http-enable";
public ApiCliConfig() {}
......
......@@ -283,52 +283,50 @@ public abstract class CliConfigFile {
}
public static class ApiConfig {
@NotEmpty private int portHttps;
@NotEmpty private int portHttp;
@NotEmpty private boolean requireHttps;
@NotEmpty private int port;
@NotEmpty private int httpPort;
@NotEmpty private boolean httpEnable;
public ApiConfig() {}
public ApiConfig(ApiConfig copy) {
this.portHttps = copy.portHttps;
this.portHttp = copy.portHttp;
this.requireHttps = copy.requireHttps;
this.port = copy.port;
this.httpPort = copy.httpPort;
this.httpEnable = copy.httpEnable;
}
public int getPortHttps() {
return portHttps;
public int getPort() {
return port;
}
public void setPortHttps(int portHttps) {
this.portHttps = portHttps;
public void setPort(int port) {
this.port = port;
}
public int getPortHttp() {
return portHttp;
public int getHttpPort() {
return httpPort;
}
public void setPortHttp(int portHttp) {
this.portHttp = portHttp;
public void setHttpPort(int httpPort) {
this.httpPort = httpPort;
}
public boolean isRequireHttps() {
return requireHttps;
public boolean isHttpEnable() {
return httpEnable;
}
public void setRequireHttps(boolean requireHttps) {
this.requireHttps = requireHttps;
public void setHttpEnable(boolean httpEnable) {
this.httpEnable = httpEnable;
}
public Map<String, String> getConfigInfo() {
Map<String, String> configInfo = new HashMap<>();
configInfo.put(
"cli/api",
"portHttps="
+ portHttps
+ ", portHttp="
+ portHttp
+ ", requireHttps="
+ Boolean.toString(requireHttps));
String info = "port=" + port;
if (httpEnable) {
info += ", httpPort=" + httpPort;
}
info += ", httpEnable=" + httpEnable;
configInfo.put("cli/api", info);
return configInfo;
}
}
......
......@@ -66,15 +66,15 @@ public class CliServicesConfig {
}
@Bean
@ConditionalOnProperty(name = ApiCliConfig.KEY_API_REQUIRE_HTTPS, havingValue = "false")
@ConditionalOnProperty(name = ApiCliConfig.KEY_API_HTTP_ENABLE, havingValue = "true")
public ServletWebServerFactory httpServer(CliConfig cliConfig) {
// https not required => configure HTTP server
int portHttp = cliConfig.getApi().getPortHttp();
int httpPort = cliConfig.getApi().getHttpPort();
if (log.isDebugEnabled()) {
log.debug("Enabling API over HTTP... portHttp=" + portHttp);
log.debug("Enabling API over HTTP... httpPort=" + httpPort);
}
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setPort(portHttp);
connector.setPort(httpPort);
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addAdditionalTomcatConnectors(connector);
return factory;
......
......@@ -25,9 +25,9 @@ public class CliWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
boolean requireHttps = cliConfig.getApi().isRequireHttps();
boolean httpEnable = cliConfig.getApi().isHttpEnable();
if (log.isDebugEnabled()) {
log.debug("Configuring REST API: requireHttps=" + requireHttps);
log.debug("Configuring REST API: httpEnable=" + httpEnable);
}
// disable CSRF
......@@ -43,7 +43,7 @@ public class CliWebSecurityConfig extends WebSecurityConfigurerAdapter {
.anyRequest()
.denyAll();
if (requireHttps) {
if (!httpEnable) {
http.requiresChannel().anyRequest().requiresSecure();
}
}
......
package com.samourai.whirlpool.cli.config.security;
import com.samourai.whirlpool.cli.config.CliConfig;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
/** Configure HTTPS server. */
@Component
public class CliWebServerFactoryCustomizer
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
private CliConfig cliConfig;
public CliWebServerFactoryCustomizer(CliConfig cliConfig) {
this.cliConfig = cliConfig;
}
@Override
public void customize(TomcatServletWebServerFactory factory) {
// configure HTTPS port
factory.setPort(cliConfig.getApi().getPort());
}
}
......@@ -119,9 +119,9 @@ public class CliService {
}
if (listen) {
String info = "API listening on https://127.0.0.1:" + cliConfig.getApi().getPortHttps();
if (!cliConfig.getApi().isRequireHttps()) {
info += " and http://127.0.0.1:" + cliConfig.getApi().getPortHttp();
String info = "API is listening on https://127.0.0.1:" + cliConfig.getApi().getPort();
if (cliConfig.getApi().isHttpEnable()) {
info += " and http://127.0.0.1:" + cliConfig.getApi().getHttpPort();
}
log.info(info);
}
......
......@@ -8,9 +8,9 @@ server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:keystore/whirlpool.p12
server.ssl.key-store-password=whirlpool
server.ssl.key-alias=whirlpool
cli.api.port-https=8899
cli.api.port-http=8898
cli.api.require-https=true
cli.api.port=8899
cli.api.http-port=8898
cli.api.http-enable=false
# cli.version
cli.server = TESTNET
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment