RPC: Add TLS

This commit is contained in:
Vincent Bernardoff 2016-12-01 20:03:39 +01:00
parent 5c428a5ea3
commit 42b30f7bd2
3 changed files with 33 additions and 15 deletions

View File

@ -54,7 +54,7 @@ let make_cors_headers ?(headers=Cohttp.Header.init ())
"Access-Control-Allow-Origin" [allowed_origin] "Access-Control-Allow-Origin" [allowed_origin]
(* Promise a running RPC server. Takes the port. *) (* Promise a running RPC server. Takes the port. *)
let launch port ?pre_hook ?post_hook root cors_allowed_origins cors_allowed_headers = let launch mode ?pre_hook ?post_hook root cors_allowed_origins cors_allowed_headers =
(* launch the worker *) (* launch the worker *)
let cancelation, canceler, _ = Lwt_utils.canceler () in let cancelation, canceler, _ = Lwt_utils.canceler () in
let open Cohttp_lwt_unix in let open Cohttp_lwt_unix in
@ -180,9 +180,7 @@ let launch port ?pre_hook ?post_hook root cors_allowed_origins cors_allowed_head
and conn_closed (_, con) = and conn_closed (_, con) =
log_info "connection close %s" (Cohttp.Connection.to_string con) ; log_info "connection close %s" (Cohttp.Connection.to_string con) ;
shutdown_stream con in shutdown_stream con in
lwt_log_info "create server listening on port %d" port >>= fun () ->
let ctx = Cohttp_lwt_unix_net.init () in let ctx = Cohttp_lwt_unix_net.init () in
let mode = `TCP (`Port port) in
let stop = cancelation () in let stop = cancelation () in
let _server = let _server =
Server.create Server.create

View File

@ -35,7 +35,7 @@ type server
another resolution mechanism. Its result is ignored if the return another resolution mechanism. Its result is ignored if the return
code is [404]. The optional [post_hook] is called if both the code is [404]. The optional [post_hook] is called if both the
[pre_hook] and the serviced answered with a [404] code. *) [pre_hook] and the serviced answered with a [404] code. *)
val launch : int -> val launch : Conduit_lwt_unix.server ->
?pre_hook: (string -> string RPC.Answer.answer Lwt.t) -> ?pre_hook: (string -> string RPC.Answer.answer Lwt.t) ->
?post_hook: (string -> string RPC.Answer.answer Lwt.t) -> ?post_hook: (string -> string RPC.Answer.answer Lwt.t) ->
unit RPC.directory -> unit RPC.directory ->

View File

@ -65,6 +65,8 @@ type cfg = {
rpc_addr : (Ipaddr.t * int) option ; rpc_addr : (Ipaddr.t * int) option ;
cors_origins : string list ; cors_origins : string list ;
cors_headers : string list ; cors_headers : string list ;
rpc_crt : string option ;
rpc_key : string option ;
(* log *) (* log *)
log_output : [`Stderr | `File of string | `Syslog | `Null] ; log_output : [`Stderr | `File of string | `Syslog | `Null] ;
@ -97,6 +99,8 @@ let default_cfg_of_base_dir base_dir = {
rpc_addr = None ; rpc_addr = None ;
cors_origins = [] ; cors_origins = [] ;
cors_headers = ["content-type"] ; cors_headers = ["content-type"] ;
rpc_crt = None ;
rpc_key = None ;
(* log *) (* log *)
log_output = `Stderr ; log_output = `Stderr ;
@ -280,8 +284,11 @@ module Cmdline = struct
(* rpc args *) (* rpc args *)
let rpc_addr = let rpc_addr =
let doc = "The TCP socket address at which this RPC server instance can be reached" in let doc = "The TCP socket address at which this RPC server instance can be reached." in
Arg.(value & opt (some sockaddr_converter) None & info ~docs:"RPC" ~doc ~docv:"ADDR:PORT" ["rpc-addr"]) Arg.(value & opt (some sockaddr_converter) None & info ~docs:"RPC" ~doc ~docv:"ADDR:PORT" ["rpc-addr"])
let rpc_tls =
let doc = "Enable TLS for this RPC server with the provided certificate and key." in
Arg.(value & opt (some (pair string string)) None & info ~docs:"RPC" ~doc ~docv:"crt,key" ["rpc-tls"])
let cors_origins = let cors_origins =
let doc = "CORS origin allowed by the RPC server via Access-Control-Allow-Origin; may be used multiple times" in let doc = "CORS origin allowed by the RPC server via Access-Control-Allow-Origin; may be used multiple times" in
Arg.(value & opt_all string [] & info ~docs:"RPC" ~doc ~docv:"ORIGIN" ["cors-origin"]) Arg.(value & opt_all string [] & info ~docs:"RPC" ~doc ~docv:"ORIGIN" ["cors-origin"])
@ -291,7 +298,8 @@ module Cmdline = struct
let parse base_dir config_file sandbox sandbox_param log_level let parse base_dir config_file sandbox sandbox_param log_level
min_connections max_connections expected_connections min_connections max_connections expected_connections
net_saddr local_discovery peers closed rpc_addr cors_origins cors_headers reset_cfg update_cfg = net_saddr local_discovery peers closed rpc_addr tls cors_origins cors_headers reset_cfg update_cfg =
let base_dir = Utils.(unopt (unopt default_cfg.base_dir base_dir) sandbox) in let base_dir = Utils.(unopt (unopt default_cfg.base_dir base_dir) sandbox) in
let config_file = Utils.(unopt ((unopt base_dir sandbox) // "config")) config_file in let config_file = Utils.(unopt ((unopt base_dir sandbox) // "config")) config_file in
let no_config () = let no_config () =
@ -317,6 +325,10 @@ module Cmdline = struct
| 1 -> Some Lwt_log.Info | 1 -> Some Lwt_log.Info
| _ -> Some Lwt_log.Debug | _ -> Some Lwt_log.Debug
in in
let rpc_crt, rpc_key = match tls with
| None -> None, None
| Some (crt, key) -> Some crt, Some key
in
let cfg = let cfg =
{ cfg with { cfg with
base_dir ; base_dir ;
@ -334,6 +346,8 @@ module Cmdline = struct
rpc_addr = Utils.first_some rpc_addr cfg.rpc_addr ; rpc_addr = Utils.first_some rpc_addr cfg.rpc_addr ;
cors_origins = (match cors_origins with [] -> cfg.cors_origins | _ -> cors_origins) ; cors_origins = (match cors_origins with [] -> cfg.cors_origins | _ -> cors_origins) ;
cors_headers = (match cors_headers with [] -> cfg.cors_headers | _ -> cors_headers) ; cors_headers = (match cors_headers with [] -> cfg.cors_headers | _ -> cors_headers) ;
rpc_crt ;
rpc_key ;
log_output = cfg.log_output ; log_output = cfg.log_output ;
} }
in in
@ -346,7 +360,7 @@ module Cmdline = struct
$ sandbox $ sandbox_param $ v $ sandbox $ sandbox_param $ v
$ min_connections $ max_connections $ expected_connections $ min_connections $ max_connections $ expected_connections
$ net_addr $ local_discovery $ peers $ closed $ net_addr $ local_discovery $ peers $ closed
$ rpc_addr $ cors_origins $ cors_headers $ rpc_addr $ rpc_tls $ cors_origins $ cors_headers
$ reset_config $ update_config $ reset_config $ update_config
), ),
let doc = "The Tezos daemon" in let doc = "The Tezos daemon" in
@ -438,16 +452,22 @@ let init_node { sandbox ; sandbox_param ;
?patch_context ?patch_context
net_params net_params
let init_rpc { rpc_addr ; cors_origins ; cors_headers } node = let init_rpc { rpc_addr ; rpc_crt; rpc_key ; cors_origins ; cors_headers } node =
match rpc_addr with match rpc_addr, rpc_crt, rpc_key with
| None -> | Some (_addr, port), Some crt, Some key ->
lwt_log_notice "Starting the RPC server listening on port %d (TLS enabled)." port >>= fun () ->
let dir = Node_rpc.build_rpc_directory node in
let mode = `TLS_native (`Crt_file_path crt, `Key_file_path key, `No_password, `Port port) in
RPC_server.launch mode dir cors_origins cors_headers >>= fun server ->
Lwt.return (Some server)
| Some (_addr, port), _, _ ->
lwt_log_notice "Starting the RPC server listening on port %d (TLS disabled)." port >>= fun () ->
let dir = Node_rpc.build_rpc_directory node in
RPC_server.launch (`TCP (`Port port)) dir cors_origins cors_headers >>= fun server ->
Lwt.return (Some server)
| _ ->
lwt_log_notice "Not listening to RPC calls." >>= fun () -> lwt_log_notice "Not listening to RPC calls." >>= fun () ->
Lwt.return None Lwt.return None
| Some (_addr, port) ->
lwt_log_notice "Starting the RPC server listening on port %d." port >>= fun () ->
let dir = Node_rpc.build_rpc_directory node in
RPC_server.launch port dir cors_origins cors_headers >>= fun server ->
Lwt.return (Some server)
let init_signal () = let init_signal () =
let handler id = try Lwt_exit.exit id with _ -> () in let handler id = try Lwt_exit.exit id with _ -> () in