11package net .b07z .sepia .proxies ;
22
3+ import java .io .BufferedInputStream ;
4+ import java .io .FileInputStream ;
5+ import java .io .IOException ;
6+ import java .security .KeyStore ;
7+ import java .util .ArrayList ;
8+ import java .util .List ;
9+ import java .util .Properties ;
10+
11+ import javax .net .ssl .SSLContext ;
12+
13+ import net .b07z .sepia .proxies .security .SSLContextBuilder ;
14+
315/**
416 * Command-line interface to start a proxy.
517 *
618 * @author Florian Quirin
719 *
820 */
921public class Start {
10-
22+
23+ //Overwrite JBoss logger
24+ //private static Logger logger;
25+ static {
26+ System .setProperty ("org.jboss.logging.provider" , "slf4j" );
27+ //logger = LoggerFactory.getLogger(Start.class);
28+ }
29+
30+ //Defaults
31+ private static String host = "localhost" ;
32+ private static int port = 20726 ;
33+ private static boolean ssl = false ;
34+ private static boolean sslSupportHttp = false ;
35+ private static String sslKeystore = "" ;
36+ private static String sslKeystorePwd = "" ;
37+
38+ private static String SETTINGS_FILE = "settings/proxy.properties" ;
39+
40+ //Command-line parameters have priority
41+ private static boolean ignoreSettingsHost = false ;
42+ private static boolean ignoreSettingsPort = false ;
43+
44+ public static void info (String msg ){
45+ System .out .println (msg );
46+ }
47+ public static void error (String msg ){
48+ //logger.error(msg);
49+ System .out .println (msg );
50+ }
51+
1152 /**
1253 * Run a proxy.
1354 * @param args
1455 * @throws Exception
1556 */
1657 public static void main (String [] args ) throws Exception {
58+
1759 String proxy = "" ;
1860
61+ //Check if arguments are given
62+ if (args == null || args .length == 0 ){
63+ error ("Missing proxy-name to run, e.g. 'tiny'." );
64+ help ();
65+ System .exit (1 );
66+ }
67+
1968 //Proxy to run:
2069 if (args [0 ].equals ("tiny" )){
2170 proxy = "tiny" ;
22-
23- //default
24- int port = 20726 ;
25- String host = "localhost" ;
71+ info ("Starting tiny proxy ..." );
2672
2773 for (String arg : args ){
2874 //Port
2975 if (arg .startsWith ("-port=" )){
3076 port = Integer .parseInt (arg .replaceFirst (".*?=" , "" ).trim ());
77+ ignoreSettingsPort = true ;
3178
3279 //Host
3380 }else if (arg .startsWith ("-host=" )){
3481 host = arg .replaceFirst (".*?=" , "" ).trim ();
82+ ignoreSettingsHost = true ;
83+
84+ //SSL
85+ }else if (arg .startsWith ("-ssl=" )){
86+ ssl = Boolean .parseBoolean (arg .replaceFirst (".*?=" , "" ).trim ());
3587
3688 //Paths
3789 }else if (arg .startsWith ("-defaultPaths=" )){
3890 String paths = arg .replaceFirst (".*?=" , "" ).trim ();
3991 if (!paths .equals ("true" )){
40- System . out . println ("Sorry any other than the default paths are not yet supported via command-line interface!" );
41- return ;
92+ error ("Sorry any other than the default paths are not yet supported via command-line interface!" );
93+ System . exit ( 1 ) ;
4294 }
4395 //TODO: add a way to define custom prefix-path combinations (best: load from config and give config-file here as value)
4496 }
4597 }
4698
47- //Create tiny reverse proxy
48- TinyReverseProxy reverseProxy = new TinyReverseProxy (host , port );
99+ //Read settings
100+ List <ProxyAction > actions = null ;
101+ KeyStore ks = null ;
102+ SSLContext sslContext = null ;
103+ try {
104+ info ("Loading settings from '" + SETTINGS_FILE + "' ..." );
105+ actions = loadSettings (SETTINGS_FILE );
106+ }catch (Exception e ){
107+ error ("Could not read '" + SETTINGS_FILE + "' file! Error: " + e .getMessage ());
108+ System .exit (1 );
109+ }
110+ //Check SSL settings and keystore
111+ if (ssl && (sslKeystore .isEmpty () || sslKeystorePwd .isEmpty ())){
112+ error ("Missing SSL keystore and/or keystore password!" );
113+ System .exit (1 );
114+ }else if (ssl ){
115+ try {
116+ ks = SSLContextBuilder .loadKeyStore (sslKeystore , sslKeystorePwd );
117+ }catch (Exception e ){
118+ error ("Could not load keystore located at: " + sslKeystore + " - check path and password!" );
119+ error ("Error msg.: " + e .getMessage ());
120+ System .exit (1 );
121+ }
122+ try {
123+ sslContext = SSLContextBuilder .create (ks , null , sslKeystorePwd );
124+ }catch (Exception e ){
125+ error ("Could not create SSLContext from keystore!" );
126+ error ("Error msg.: " + e .getMessage ());
127+ System .exit (1 );
128+ }
129+ }
49130
50- //Add paths - SEPIA defaults for custom-bundle:
51- reverseProxy .addPrefixPath ("/sepia/assist" , "http://localhost:20721" );
52- reverseProxy .addPrefixPath ("/sepia/teach" , "http://localhost:20722" );
53- reverseProxy .addPrefixPath ("/sepia/chat" , "http://localhost:20723" );
131+ //Create tiny reverse proxy
132+ TinyReverseProxy reverseProxy = new TinyReverseProxy (host , port , ssl , sslContext );
133+ reverseProxy .setSslHttpSupport (sslSupportHttp , (port + 1 )); //HTTP support is done via listener on PORT+1
134+
135+ //Add actions
136+ for (ProxyAction pa : actions ){
137+ if (pa .actionType .equals ("redirect" )){
138+ reverseProxy .addPrefixPath (pa .redirectPath , pa .redirectTarget , pa .targetIsPublic );
139+ }
140+ }
141+ /*
142+ reverseProxy.addPrefixPath("/sepia/assist", "http://localhost:20721", true);
143+ */
54144
55145 //Start proxy
56146 reverseProxy .start ();
57147
58148 //Note
59- System .out .println ("SEPIA '" + proxy + "' reverse proxy started at: " + host + ":" + port );
149+ info ("\n SEPIA '" + proxy + "' reverse proxy started as: " + host + ":" + port );
150+ info ("Using SSL: " + ssl );
151+ if (ssl ){
152+ info ("SSL keystore: " + sslKeystore );
153+ if (sslSupportHttp ){
154+ info ("NOTE: All calls to simple HTTP are available at port: " + (port + 1 ));
155+ }else {
156+ info ("NOTE: All calls to simple HTTP are deactivated when SSL is active!" );
157+ }
158+ }
60159
61160 return ;
62161
@@ -71,11 +170,76 @@ public static void main(String[] args) throws Exception {
71170 * Command-line interface help.
72171 */
73172 private static void help (){
74- System .out .println ("\n Usage:" );
75- System .out .println ("[proxy-name] [arguments]" );
76- System .out .println ("\n Proxies:" );
77- System .out .println ("tiny - args: -defaultPaths=true, -port=20726, -host=localhost" );
78- System .out .println ("" );
173+ info ("\n Usage:" );
174+ info ("[proxy-name] [arguments]" );
175+ info ("\n Proxies:" );
176+ info ("tiny - args: -defaultPaths=true, -port=20726, -host=localhost, -ssl=true" );
177+ info ("\n Configuration is done via 'settings/proxy.properties' file." );
178+ info ("" );
179+ }
180+
181+ /**
182+ * Class holding proxy actions loaded from settings.
183+ */
184+ private static class ProxyAction {
185+ String redirectPath ;
186+ String redirectTarget ;
187+ boolean targetIsPublic = false ;
188+ String actionType = "" ;
189+
190+ public ProxyAction (){}
191+
192+ public ProxyAction setRedirect (String path , String target , boolean isPublic ){
193+ this .redirectPath = path ;
194+ this .redirectTarget = target ;
195+ this .targetIsPublic = isPublic ;
196+ this .actionType = "redirect" ;
197+ return this ;
198+ }
199+ }
200+
201+ /**
202+ * Load settings from properties file and return actions list.
203+ * @param configFile - path and file
204+ * @throws IOException
205+ */
206+ private static List <ProxyAction > loadSettings (String configFile ) throws IOException {
207+ BufferedInputStream stream =null ;
208+ Properties config = new Properties ();
209+ stream = new BufferedInputStream (new FileInputStream (configFile ));
210+ config .load (stream );
211+ stream .close ();
212+ List <ProxyAction > actions = new ArrayList <>();
213+ for (Object key : config .keySet ()){
214+ String entry = (String ) key ;
215+ //has to be format: action_type_name, e.g. redirect_path_1
216+ //has to have types: path, target, public
217+ if (entry .startsWith ("redirect" )){
218+ String [] info = entry .split ("_" );
219+ if (info .length != 3 ){
220+ throw new RuntimeException ("Settings file has invalid format in entry: " + entry );
221+ }else {
222+ String name = info [2 ];
223+ String path = config .getProperty ("redirect_path_" + name );
224+ String target = config .getProperty ("redirect_target_" + name );
225+ boolean isPublic = Boolean .parseBoolean (config .getProperty ("redirect_public_" + name ));
226+ actions .add (new ProxyAction ().setRedirect (path , target , isPublic ));
227+ }
228+
229+ }else if (entry .equals ("host" ) && !ignoreSettingsHost ){
230+ host = config .getProperty (entry );
231+ }else if (entry .equals ("port" ) && !ignoreSettingsPort ){
232+ port = Integer .parseInt (config .getProperty (entry ));
233+
234+ }else if (entry .equals ("ssl_keystore" )){
235+ sslKeystore = config .getProperty (entry );
236+ }else if (entry .equals ("ssl_keystore_pwd" )){
237+ sslKeystorePwd = config .getProperty (entry );
238+ }else if (entry .equals ("ssl_support_http" )){
239+ sslSupportHttp = Boolean .parseBoolean (config .getProperty (entry ));
240+ }
241+ }
242+ return actions ;
79243 }
80244
81245}
0 commit comments