Signer: support plain HTTP (no S) and a few cosmetic fixes
This commit is contained in:
parent
0bb12b0655
commit
7ad44a9af3
@ -59,7 +59,17 @@ let sign
|
||||
let public_key (cctxt : #Client_context.wallet) pkh =
|
||||
log "Request for public key %a"
|
||||
Signature.Public_key_hash.pp pkh >>= fun () ->
|
||||
Client_keys.get_public_key cctxt pkh >>=? fun (name, pk) ->
|
||||
log "Found public key for hash %a (name: %s)"
|
||||
Signature.Public_key_hash.pp pkh name >>= fun () ->
|
||||
return pk
|
||||
Client_keys.list_keys cctxt >>=? fun all_keys ->
|
||||
match List.find (fun (_, h, _, _) -> Signature.Public_key_hash.equal h pkh) all_keys with
|
||||
| exception Not_found ->
|
||||
log "No public key found for hash %a"
|
||||
Signature.Public_key_hash.pp pkh >>= fun () ->
|
||||
Lwt.fail Not_found
|
||||
| (_, _, None, _) ->
|
||||
log "No public key found for hash %a"
|
||||
Signature.Public_key_hash.pp pkh >>= fun () ->
|
||||
Lwt.fail Not_found
|
||||
| (name, _, Some pk, _) ->
|
||||
log "Found public key for hash %a (name: %s)"
|
||||
Signature.Public_key_hash.pp pkh name >>= fun () ->
|
||||
return pk
|
||||
|
66
src/bin_signer/http_daemon.ml
Normal file
66
src/bin_signer/http_daemon.ml
Normal file
@ -0,0 +1,66 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
let log = Signer_logging.lwt_log_notice
|
||||
|
||||
let run (cctxt : #Client_context.wallet) ~hosts ?magic_bytes ~require_auth mode =
|
||||
let dir = RPC_directory.empty in
|
||||
let dir =
|
||||
RPC_directory.register1 dir Signer_services.sign begin fun pkh signature data ->
|
||||
Handler.sign cctxt { pkh ; data ; signature } ?magic_bytes ~require_auth
|
||||
end in
|
||||
let dir =
|
||||
RPC_directory.register1 dir Signer_services.public_key begin fun pkh () () ->
|
||||
Handler.public_key cctxt pkh
|
||||
end in
|
||||
let dir =
|
||||
RPC_directory.register0 dir Signer_services.authorized_keys begin fun () () ->
|
||||
if require_auth then
|
||||
return None
|
||||
else
|
||||
Handler.Authorized_key.load cctxt >>=? fun keys ->
|
||||
return (Some (keys |> List.split |> snd |> List.map Signature.Public_key.hash))
|
||||
end in
|
||||
Lwt.catch
|
||||
(fun () ->
|
||||
List.map
|
||||
(fun host ->
|
||||
let host = Ipaddr.V6.to_string host in
|
||||
log "Listening on address %s" host >>= fun () ->
|
||||
RPC_server.launch ~host mode dir
|
||||
~media_types:Media_type.all_media_types
|
||||
>>= fun _server ->
|
||||
fst (Lwt.wait ()))
|
||||
hosts |> Lwt.choose)
|
||||
(function
|
||||
| Unix.Unix_error(Unix.EADDRINUSE, "bind","") ->
|
||||
failwith "Port already in use."
|
||||
| exn -> Lwt.return (error_exn exn))
|
||||
|
||||
let run_https (cctxt : #Client_context.wallet) ~host ~port ~cert ~key ?magic_bytes ~require_auth =
|
||||
Lwt_utils_unix.getaddrinfo ~passive:true ~node:host ~service:(string_of_int port) >>= function
|
||||
| []->
|
||||
failwith "Cannot resolve listening address: %S" host
|
||||
| points ->
|
||||
let hosts = fst (List.split points) in
|
||||
log "Accepting HTTPS requests on port %d" port >>= fun () ->
|
||||
let mode : Conduit_lwt_unix.server =
|
||||
`TLS (`Crt_file_path cert, `Key_file_path key, `No_password, `Port port) in
|
||||
run (cctxt : #Client_context.wallet) ~hosts ?magic_bytes ~require_auth mode
|
||||
|
||||
let run_http (cctxt : #Client_context.wallet) ~host ~port ?magic_bytes ~require_auth =
|
||||
Lwt_utils_unix.getaddrinfo ~passive:true ~node:host ~service:(string_of_int port) >>= function
|
||||
| [] ->
|
||||
failwith "Cannot resolve listening address: %S" host
|
||||
| points ->
|
||||
let hosts = fst (List.split points) in
|
||||
log "Accepting HTTP requests on port %d" port >>= fun () ->
|
||||
let mode : Conduit_lwt_unix.server =
|
||||
`TCP (`Port port) in
|
||||
run (cctxt : #Client_context.wallet) ~hosts ?magic_bytes ~require_auth mode
|
@ -7,9 +7,16 @@
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
val run:
|
||||
val run_https:
|
||||
#Client_context.io_wallet ->
|
||||
host:string -> port:int -> cert:string -> key:string ->
|
||||
?magic_bytes: int list ->
|
||||
require_auth: bool ->
|
||||
'a tzresult Lwt.t
|
||||
|
||||
val run_http:
|
||||
#Client_context.io_wallet ->
|
||||
host:string -> port:int ->
|
||||
?magic_bytes: int list ->
|
||||
require_auth: bool ->
|
||||
'a tzresult Lwt.t
|
@ -1,44 +0,0 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
let log = Signer_logging.lwt_log_notice
|
||||
|
||||
let run (cctxt : #Client_context.wallet) ~host ~port ~cert ~key ?magic_bytes ~require_auth =
|
||||
log "Accepting HTTPS requests on port %d" port >>= fun () ->
|
||||
let mode : Conduit_lwt_unix.server =
|
||||
`TLS (`Crt_file_path cert, `Key_file_path key, `No_password, `Port port) in
|
||||
let dir = RPC_directory.empty in
|
||||
let dir =
|
||||
RPC_directory.register1 dir Signer_services.sign begin fun pkh signature data ->
|
||||
Handler.sign cctxt { pkh ; data ; signature } ?magic_bytes ~require_auth
|
||||
end in
|
||||
let dir =
|
||||
RPC_directory.register1 dir Signer_services.public_key begin fun pkh () () ->
|
||||
Handler.public_key cctxt pkh
|
||||
end in
|
||||
let dir =
|
||||
RPC_directory.register0 dir Signer_services.authorized_keys begin fun () () ->
|
||||
if require_auth then
|
||||
return None
|
||||
else
|
||||
Handler.Authorized_key.load cctxt >>=? fun keys ->
|
||||
return (Some (keys |> List.split |> snd |> List.map Signature.Public_key.hash))
|
||||
end in
|
||||
Lwt.catch
|
||||
(fun () ->
|
||||
RPC_server.launch ~host mode dir
|
||||
~media_types:Media_type.all_media_types
|
||||
~cors: { allowed_origins = [ "*" ] ;
|
||||
allowed_headers = [ "Content-Type" ] }
|
||||
>>= fun _server ->
|
||||
fst (Lwt.wait ()))
|
||||
(function
|
||||
| Unix.Unix_error(Unix.EADDRINUSE, "bind","") ->
|
||||
failwith "Port already in use."
|
||||
| exn -> Lwt.return (error_exn exn))
|
@ -32,6 +32,16 @@ let default_https_port =
|
||||
| None -> "443"
|
||||
| Some port -> port
|
||||
|
||||
let default_http_host =
|
||||
match Sys.getenv_opt "TEZOS_SIGNER_HTTP_HOST" with
|
||||
| None -> "localhost"
|
||||
| Some host -> host
|
||||
|
||||
let default_http_port =
|
||||
match Sys.getenv_opt "TEZOS_SIGNER_HTTP_PORT" with
|
||||
| None -> "6732"
|
||||
| Some port -> port
|
||||
|
||||
open Clic
|
||||
|
||||
let group =
|
||||
@ -98,6 +108,31 @@ let commands base_dir require_auth =
|
||||
(fun (magic_bytes, path) cctxt ->
|
||||
Tezos_signer_backends.Encrypted.decrypt_all cctxt >>=? fun () ->
|
||||
Socket_daemon.run cctxt (Unix path) ?magic_bytes ~require_auth) ;
|
||||
command ~group
|
||||
~desc: "Launch a signer daemon over HTTP."
|
||||
(args3
|
||||
magic_bytes_arg
|
||||
(default_arg
|
||||
~doc: "listening address or host name"
|
||||
~short: 'a'
|
||||
~long: "address"
|
||||
~placeholder: "host|address"
|
||||
~default: default_http_host
|
||||
(parameter (fun _ s -> return s)))
|
||||
(default_arg
|
||||
~doc: "listening HTTP port"
|
||||
~short: 'p'
|
||||
~long: "port"
|
||||
~placeholder: "port number"
|
||||
~default: default_http_port
|
||||
(parameter
|
||||
(fun _ x ->
|
||||
try return (int_of_string x)
|
||||
with Failure _ -> failwith "Invalid port %s" x))))
|
||||
(prefixes [ "launch" ; "http" ; "signer" ] @@ stop)
|
||||
(fun (magic_bytes, host, port) cctxt ->
|
||||
Tezos_signer_backends.Encrypted.decrypt_all cctxt >>=? fun () ->
|
||||
Http_daemon.run_http cctxt ~host ~port ?magic_bytes ~require_auth) ;
|
||||
command ~group
|
||||
~desc: "Launch a signer daemon over HTTPS."
|
||||
(args3
|
||||
@ -123,14 +158,22 @@ let commands base_dir require_auth =
|
||||
param
|
||||
~name:"cert"
|
||||
~desc: "path to th TLS certificate"
|
||||
(parameter (fun _ s -> return s)) @@
|
||||
(parameter (fun _ s ->
|
||||
if not (Sys.file_exists s) then
|
||||
failwith "No such TLS certificate file %s" s
|
||||
else
|
||||
return s)) @@
|
||||
param
|
||||
~name:"key"
|
||||
~desc: "path to th TLS key"
|
||||
(parameter (fun _ s -> return s)) @@ stop)
|
||||
(parameter (fun _ s ->
|
||||
if not (Sys.file_exists s) then
|
||||
failwith "No such TLS key file %s" s
|
||||
else
|
||||
return s)) @@ stop)
|
||||
(fun (magic_bytes, host, port) cert key cctxt ->
|
||||
Tezos_signer_backends.Encrypted.decrypt_all cctxt >>=? fun () ->
|
||||
Https_daemon.run cctxt ~host ~port ~cert ~key ?magic_bytes ~require_auth) ;
|
||||
Http_daemon.run_https cctxt ~host ~port ~cert ~key ?magic_bytes ~require_auth) ;
|
||||
command ~group
|
||||
~desc: "Authorize a given public key to perform signing requests."
|
||||
(args1
|
||||
|
@ -193,13 +193,13 @@ let raw_get_key (cctxt : #Client_context.wallet) pkh =
|
||||
let get_key cctxt pkh =
|
||||
raw_get_key cctxt pkh >>=? function
|
||||
| (pkh, Some pk, Some sk) -> return (pkh, pk, sk)
|
||||
| (_pkh, _pk, None) -> failwith "... FIXME ... E"
|
||||
| (_pkh, None, _sk) -> failwith "... FIXME ... F"
|
||||
| (_pkh, _pk, None) -> failwith "Unknown secret key for %a" Signature.Public_key_hash.pp pkh
|
||||
| (_pkh, None, _sk) -> failwith "Unknown public key for %a" Signature.Public_key_hash.pp pkh
|
||||
|
||||
let get_public_key cctxt pkh =
|
||||
raw_get_key cctxt pkh >>=? function
|
||||
| (pkh, Some pk, _sk) -> return (pkh, pk)
|
||||
| (_pkh, None, _sk) -> failwith "... FIXME ... G"
|
||||
| (_pkh, None, _sk) -> failwith "Unknown public key for %a" Signature.Public_key_hash.pp pkh
|
||||
|
||||
let get_keys (cctxt : #Client_context.wallet) =
|
||||
Secret_key.load cctxt >>=? fun sks ->
|
||||
|
@ -110,7 +110,7 @@ let main select_commands =
|
||||
(module Tezos_signer_backends.Encrypted.Make(struct
|
||||
let cctxt = (client_config :> Client_context.prompter)
|
||||
end)) ;
|
||||
let module Remote_authenticator = struct
|
||||
let module Remote_params = struct
|
||||
let authenticate pkhs payload =
|
||||
Client_keys.list_keys client_config >>=? fun keys ->
|
||||
match List.filter_map
|
||||
@ -125,17 +125,20 @@ let main select_commands =
|
||||
| [] -> failwith
|
||||
"remote signer expects authentication signature, \
|
||||
but no authorized key was found in the wallet"
|
||||
let logger = rpc_config.logger
|
||||
end in
|
||||
let module Https = Tezos_signer_backends.Https.Make(Remote_authenticator) in
|
||||
let module Socket = Tezos_signer_backends.Socket.Make(Remote_authenticator) in
|
||||
let module Https = Tezos_signer_backends.Https.Make(Remote_params) in
|
||||
let module Http = Tezos_signer_backends.Http.Make(Remote_params) in
|
||||
let module Socket = Tezos_signer_backends.Socket.Make(Remote_params) in
|
||||
Client_keys.register_signer (module Https) ;
|
||||
Client_keys.register_signer (module Http) ;
|
||||
Client_keys.register_signer (module Socket.Unix) ;
|
||||
Client_keys.register_signer (module Socket.Tcp) ;
|
||||
Option.iter parsed_config_file.remote_signer ~f: begin fun signer ->
|
||||
Client_keys.register_signer
|
||||
(module Tezos_signer_backends.Remote.Make(struct
|
||||
let default = signer
|
||||
include Remote_authenticator
|
||||
include Remote_params
|
||||
end))
|
||||
end ;
|
||||
select_commands ctxt parsed_args >>=? fun commands ->
|
||||
|
@ -41,7 +41,7 @@ module Raw = struct
|
||||
| None -> return None
|
||||
| Some bytes ->
|
||||
match Data_encoding.Binary.of_bytes Signature.Secret_key.encoding bytes with
|
||||
| None -> failwith "... FIXME ... D" (* corrupted data *)
|
||||
| None -> failwith "Corrupted wallet, deciphered key is invalid"
|
||||
| Some sk -> return (Some sk)
|
||||
|
||||
end
|
||||
@ -77,7 +77,7 @@ let rec noninteractice_decrypt_loop ~encrypted_sk = function
|
||||
|
||||
let decrypt_payload cctxt ?name encrypted_sk =
|
||||
match Base58.safe_decode encrypted_sk with
|
||||
| None -> failwith "... FIXME ... A"
|
||||
| None -> failwith "Not a Base58 encoded encrypted key"
|
||||
| Some encrypted_sk ->
|
||||
let encrypted_sk = MBytes.of_string encrypted_sk in
|
||||
noninteractice_decrypt_loop ~encrypted_sk !passwords >>=? function
|
||||
|
10
src/lib_signer_backends/http.ml
Normal file
10
src/lib_signer_backends/http.ml
Normal file
@ -0,0 +1,10 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
include Http_gen.Make(struct let scheme = "http" end)
|
16
src/lib_signer_backends/http.mli
Normal file
16
src/lib_signer_backends/http.mli
Normal file
@ -0,0 +1,16 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
val logger: RPC_client.logger
|
||||
end)
|
||||
: Client_keys.SIGNER
|
||||
|
||||
val make_base: string -> int -> Uri.t
|
91
src/lib_signer_backends/http_gen.ml
Normal file
91
src/lib_signer_backends/http_gen.ml
Normal file
@ -0,0 +1,91 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
module Make(N : sig val scheme : string end) = struct
|
||||
|
||||
open Client_keys
|
||||
|
||||
let scheme = N.scheme
|
||||
|
||||
module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
val logger: RPC_client.logger
|
||||
end) = struct
|
||||
|
||||
let scheme = scheme
|
||||
|
||||
let title =
|
||||
"Built-in tezos-signer using remote signer through hardcoded " ^ scheme ^ " requests."
|
||||
|
||||
let description =
|
||||
"Valid locators are of this form:\n"
|
||||
^ " - " ^ scheme ^ "://host/tz1...\n"
|
||||
^ " - " ^ scheme ^ "://host:port/path/to/service/tz1..."
|
||||
|
||||
let parse uri =
|
||||
(* extract `tz1..` from the last component of the path *)
|
||||
assert (Uri.scheme uri = Some scheme) ;
|
||||
let path = Uri.path uri in
|
||||
begin match String.rindex_opt path '/' with
|
||||
| None ->
|
||||
failwith "Invalid locator %a" Uri.pp_hum uri
|
||||
| Some i ->
|
||||
let pkh = String.sub path (i + 1) (String.length path - i - 1) in
|
||||
let path = String.sub path 0 i in
|
||||
return (Uri.with_path uri path, pkh)
|
||||
end >>=? fun (base, pkh) ->
|
||||
Lwt.return (Signature.Public_key_hash.of_b58check pkh) >>=? fun pkh ->
|
||||
return (base, pkh)
|
||||
|
||||
let public_key uri =
|
||||
parse (uri : pk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||
RPC_client.call_service
|
||||
~logger: P.logger
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.public_key ((), pkh) () ()
|
||||
|
||||
let neuterize uri =
|
||||
return (Client_keys.make_pk_uri (uri : sk_uri :> Uri.t))
|
||||
|
||||
let public_key_hash uri =
|
||||
public_key uri >>=? fun pk ->
|
||||
return (Signature.Public_key.hash pk)
|
||||
|
||||
let sign ?watermark uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||
let msg =
|
||||
match watermark with
|
||||
| None -> msg
|
||||
| Some watermark ->
|
||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||
RPC_client.call_service
|
||||
~logger: P.logger
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.authorized_keys () () () >>=? fun authorized_keys ->
|
||||
begin match authorized_keys with
|
||||
| Some authorized_keys ->
|
||||
P.authenticate
|
||||
authorized_keys
|
||||
(Signer_messages.Sign.Request.to_sign ~pkh ~data:msg) >>=? fun signature ->
|
||||
return (Some signature)
|
||||
| None -> return None
|
||||
end >>=? fun signature ->
|
||||
RPC_client.call_service
|
||||
~logger: P.logger
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.sign ((), pkh)
|
||||
signature
|
||||
msg
|
||||
|
||||
end
|
||||
|
||||
let make_base host port =
|
||||
Uri.make ~scheme ~host ~port ()
|
||||
|
||||
end
|
20
src/lib_signer_backends/http_gen.mli
Normal file
20
src/lib_signer_backends/http_gen.mli
Normal file
@ -0,0 +1,20 @@
|
||||
(**************************************************************************)
|
||||
(* *)
|
||||
(* Copyright (c) 2014 - 2018. *)
|
||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||
(* *)
|
||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
module Make(N : sig val scheme : string end) : sig
|
||||
|
||||
module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
val logger: RPC_client.logger
|
||||
end)
|
||||
: Client_keys.SIGNER
|
||||
|
||||
val make_base: string -> int -> Uri.t
|
||||
|
||||
end
|
@ -7,77 +7,4 @@
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
open Client_keys
|
||||
|
||||
let scheme = "https"
|
||||
|
||||
module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
end) = struct
|
||||
|
||||
let scheme = scheme
|
||||
|
||||
let title =
|
||||
"Built-in tezos-signer using remote signer through hardcoded https requests."
|
||||
|
||||
let description =
|
||||
"Valid locators are of this form:\n\
|
||||
\ - https://host/tz1...\n\
|
||||
\ - https://host:port/path/to/service/tz1...\n"
|
||||
|
||||
let parse uri =
|
||||
(* extract `tz1..` from the last component of the path *)
|
||||
assert (Uri.scheme uri = Some scheme) ;
|
||||
let path = Uri.path uri in
|
||||
begin match String.rindex_opt path '/' with
|
||||
| None ->
|
||||
failwith "Invalid locator %a" Uri.pp_hum uri
|
||||
| Some i ->
|
||||
let pkh = String.sub path (i + 1) (String.length path - i - 1) in
|
||||
let path = String.sub path 0 i in
|
||||
return (Uri.with_path uri path, pkh)
|
||||
end >>=? fun (base, pkh) ->
|
||||
Lwt.return (Signature.Public_key_hash.of_b58check pkh) >>=? fun pkh ->
|
||||
return (base, pkh)
|
||||
|
||||
let public_key uri =
|
||||
parse (uri : pk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||
RPC_client.call_service
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.public_key ((), pkh) () ()
|
||||
|
||||
let neuterize uri =
|
||||
return (Client_keys.make_pk_uri (uri : sk_uri :> Uri.t))
|
||||
|
||||
let public_key_hash uri =
|
||||
public_key uri >>=? fun pk ->
|
||||
return (Signature.Public_key.hash pk)
|
||||
|
||||
let sign ?watermark uri msg =
|
||||
parse (uri : sk_uri :> Uri.t) >>=? fun (base, pkh) ->
|
||||
let msg =
|
||||
match watermark with
|
||||
| None -> msg
|
||||
| Some watermark ->
|
||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||
RPC_client.call_service
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.authorized_keys () () () >>=? fun authorized_keys ->
|
||||
begin match authorized_keys with
|
||||
| Some authorized_keys ->
|
||||
P.authenticate
|
||||
authorized_keys
|
||||
(Signer_messages.Sign.Request.to_sign ~pkh ~data:msg) >>=? fun signature ->
|
||||
return (Some signature)
|
||||
| None -> return None
|
||||
end >>=? fun signature ->
|
||||
RPC_client.call_service
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.sign ((), pkh)
|
||||
signature
|
||||
msg
|
||||
|
||||
end
|
||||
|
||||
let make_base host port =
|
||||
Uri.make ~scheme ~host ~port ()
|
||||
include Http_gen.Make(struct let scheme = "https" end)
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
val logger: RPC_client.logger
|
||||
end)
|
||||
: Client_keys.SIGNER
|
||||
|
||||
|
@ -14,6 +14,7 @@ let scheme = "remote"
|
||||
module Make(S : sig
|
||||
val default : Uri.t
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
val logger: RPC_client.logger
|
||||
end) = struct
|
||||
|
||||
let scheme = scheme
|
||||
@ -25,18 +26,21 @@ module Make(S : sig
|
||||
"Valid locators are of this form: remote://tz1...\n\
|
||||
The key will be queried to current remote signer, which can be \
|
||||
configured with the `--remote-signer` or `-R` options, \
|
||||
or by defining the following environment variables:\n \
|
||||
- $TEZOS_SIGNER_UNIX_PATH,\n\
|
||||
- $TEZOS_SIGNER_TCP_HOST and $TEZOS_SIGNER_TCP_PORT (default: 7732),\n\
|
||||
- $TEZOS_SIGNER_HTTPS_HOST and $TEZOS_SIGNER_HTTPS_PORT (default: 443)."
|
||||
or by defining the following environment variables:\n\
|
||||
\ - $TEZOS_SIGNER_UNIX_PATH,\n\
|
||||
\ - $TEZOS_SIGNER_TCP_HOST and $TEZOS_SIGNER_TCP_PORT (default: 7732),\n\
|
||||
\ - $TEZOS_SIGNER_HTTP_HOST and $TEZOS_SIGNER_HTTP_PORT (default: 6732),\n\
|
||||
\ - $TEZOS_SIGNER_HTTPS_HOST and $TEZOS_SIGNER_HTTPS_PORT (default: 443)."
|
||||
|
||||
module Socket = Socket.Make(S)
|
||||
module Http = Http.Make(S)
|
||||
module Https = Https.Make(S)
|
||||
|
||||
let get_remote () =
|
||||
match Uri.scheme S.default with
|
||||
| Some "unix" -> (module Socket.Unix : SIGNER)
|
||||
| Some "tcp" -> (module Socket.Tcp : SIGNER)
|
||||
| Some "http" -> (module Http : SIGNER)
|
||||
| Some "https" -> (module Https : SIGNER)
|
||||
| _ -> assert false
|
||||
|
||||
@ -51,7 +55,7 @@ module Make(S : sig
|
||||
(fun uri ->
|
||||
let key = Uri.path uri in
|
||||
Uri.with_path S.default key)
|
||||
| Some "https" ->
|
||||
| Some ("https" | "http") ->
|
||||
(fun uri ->
|
||||
let key = Uri.path uri in
|
||||
match Uri.path S.default with
|
||||
@ -89,11 +93,12 @@ let make_pk pk =
|
||||
let read_base_uri_from_env () =
|
||||
match Sys.getenv_opt "TEZOS_SIGNER_UNIX_PATH",
|
||||
Sys.getenv_opt "TEZOS_SIGNER_TCP_HOST",
|
||||
Sys.getenv_opt "TEZOS_SIGNER_HTTP_HOST",
|
||||
Sys.getenv_opt "TEZOS_SIGNER_HTTPS_HOST" with
|
||||
| None, None, None -> return None
|
||||
| Some path, None, None ->
|
||||
| None, None, None, None -> return None
|
||||
| Some path, None, None, None ->
|
||||
return (Some (Socket.make_unix_base path))
|
||||
| None, Some host, None -> begin
|
||||
| None, Some host, None, None -> begin
|
||||
try
|
||||
let port =
|
||||
match Sys.getenv_opt "TEZOS_SIGNER_TCP_PORT" with
|
||||
@ -103,7 +108,17 @@ let read_base_uri_from_env () =
|
||||
with Invalid_argument _ ->
|
||||
failwith "Failed to parse TEZOS_SIGNER_TCP_PORT.@."
|
||||
end
|
||||
| None, None, Some host -> begin
|
||||
| None, None, Some host, None -> begin
|
||||
try
|
||||
let port =
|
||||
match Sys.getenv_opt "TEZOS_SIGNER_HTTP_PORT" with
|
||||
| None -> 6732
|
||||
| Some port -> int_of_string port in
|
||||
return (Some (Http.make_base host port))
|
||||
with Invalid_argument _ ->
|
||||
failwith "Failed to parse TEZOS_SIGNER_HTTP_PORT.@."
|
||||
end
|
||||
| None, None, None, Some host -> begin
|
||||
try
|
||||
let port =
|
||||
match Sys.getenv_opt "TEZOS_SIGNER_HTTPS_PORT" with
|
||||
@ -113,11 +128,12 @@ let read_base_uri_from_env () =
|
||||
with Invalid_argument _ ->
|
||||
failwith "Failed to parse TEZOS_SIGNER_HTTPS_PORT.@."
|
||||
end
|
||||
| _, _, _ ->
|
||||
| _, _, _, _ ->
|
||||
failwith
|
||||
"Only one the following environment variable must be defined: \
|
||||
TEZOS_SIGNER_UNIX_PATH, \
|
||||
TEZOS_SIGNER_TCP_HOST, \
|
||||
TEZOS_SIGNER_HTTP_HOST, \
|
||||
TEZOS_SIGNER_HTTPS_HOST@."
|
||||
|
||||
type error += Invalid_remote_signer of string
|
||||
@ -130,7 +146,13 @@ let () =
|
||||
~description: "The provided remote signer is invalid."
|
||||
~pp:
|
||||
(fun ppf s ->
|
||||
Format.fprintf ppf "Value '%s' is not a valid URI for a remote signer" s)
|
||||
Format.fprintf ppf
|
||||
"@[<v 0>Value '%s' is not a valid URI for a remote signer.@,\
|
||||
Supported URIs for remote signers are of the form:@,\
|
||||
\ - unix:///path/to/socket/file@,\
|
||||
\ - tcp://host:port@,\
|
||||
\ - http://host[:port][/prefix]@,\
|
||||
\ - https://host[:port][/prefix]@]" s)
|
||||
Data_encoding.(obj1 (req "uri" string))
|
||||
(function Invalid_remote_signer s -> Some s | _ -> None)
|
||||
(fun s -> Invalid_remote_signer s)
|
||||
@ -140,6 +162,7 @@ let parse_base_uri s =
|
||||
try
|
||||
let uri = Uri.of_string s in
|
||||
match Uri.scheme uri with
|
||||
| Some "http" -> return uri
|
||||
| Some "https" -> return uri
|
||||
| Some "tcp" -> return uri
|
||||
| Some "unix" -> return uri
|
||||
|
@ -10,6 +10,7 @@
|
||||
module Make(S : sig
|
||||
val default : Uri.t
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
val logger: RPC_client.logger
|
||||
end) : Client_keys.SIGNER
|
||||
|
||||
val make_pk: Signature.public_key -> Client_keys.pk_uri
|
||||
|
@ -23,14 +23,14 @@ let sign =
|
||||
~query
|
||||
~input: Data_encoding.bytes
|
||||
~output: Data_encoding.(obj1 (req "signature" Signature.encoding))
|
||||
RPC_path.(root /: Signature.Public_key_hash.rpc_arg)
|
||||
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
||||
|
||||
let public_key =
|
||||
RPC_service.get_service
|
||||
~description: "Retrieve the public key of a given remote key"
|
||||
~query: RPC_query.empty
|
||||
~output: Data_encoding.(obj1 (req "public_key" Signature.Public_key.encoding))
|
||||
RPC_path.(root /: Signature.Public_key_hash.rpc_arg)
|
||||
RPC_path.(root / "keys" /: Signature.Public_key_hash.rpc_arg)
|
||||
|
||||
let authorized_keys =
|
||||
RPC_service.get_service
|
||||
|
Loading…
Reference in New Issue
Block a user