Signer: add authorized keys mechanism
This commit is contained in:
parent
a8b2ab325e
commit
347a552396
@ -9,11 +9,35 @@
|
||||
|
||||
let log = Signer_logging.lwt_log_notice
|
||||
|
||||
let sign (cctxt : #Client_context.wallet) pkh data =
|
||||
module Authorized_key =
|
||||
Client_aliases.Alias (struct
|
||||
include Signature.Public_key
|
||||
let name = "authorized_key"
|
||||
let to_source s = return (to_b58check s)
|
||||
let of_source t = Lwt.return (of_b58check t)
|
||||
end)
|
||||
|
||||
let sign
|
||||
(cctxt : #Client_context.wallet)
|
||||
Signer_messages.Sign.Request.{ pkh ; data ; signature } ~require_auth =
|
||||
log "Request for signing %d bytes of data for key %a, magic byte = %02X"
|
||||
(MBytes.length data)
|
||||
Signature.Public_key_hash.pp pkh
|
||||
(MBytes.get_uint8 data 0) >>= fun () ->
|
||||
begin match require_auth, signature with
|
||||
| false, _ -> return ()
|
||||
| true, None -> failwith "missing authentication signature field"
|
||||
| true, Some signature ->
|
||||
let to_sign = Signer_messages.Sign.Request.to_sign ~pkh ~data in
|
||||
Authorized_key.load cctxt >>=? fun keys ->
|
||||
if List.fold_left
|
||||
(fun acc (_, key) -> acc || Signature.check key signature to_sign)
|
||||
false keys
|
||||
then
|
||||
return ()
|
||||
else
|
||||
failwith "invalid authentication signature"
|
||||
end >>=? fun () ->
|
||||
Client_keys.get_key cctxt pkh >>=? fun (name, _pkh, sk_uri) ->
|
||||
log "Signing data for key %s" name >>= fun () ->
|
||||
Client_keys.sign sk_uri data >>=? fun signature ->
|
||||
|
@ -9,19 +9,27 @@
|
||||
|
||||
let log = Signer_logging.lwt_log_notice
|
||||
|
||||
let run (cctxt : #Client_context.wallet) ~host ~port ~cert ~key =
|
||||
let run (cctxt : #Client_context.wallet) ~host ~port ~cert ~key ~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 () data ->
|
||||
Handler.sign cctxt pkh data
|
||||
RPC_directory.register1 dir Signer_services.sign begin fun pkh signature data ->
|
||||
Handler.sign cctxt { pkh ; data ; signature } ~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
|
||||
|
@ -9,4 +9,6 @@
|
||||
|
||||
val run:
|
||||
#Client_context.io_wallet ->
|
||||
host:string -> port:int -> cert:string -> key:string -> 'a tzresult Lwt.t
|
||||
host:string -> port:int -> cert:string -> key:string ->
|
||||
require_auth: bool ->
|
||||
'a tzresult Lwt.t
|
||||
|
@ -38,7 +38,7 @@ let group =
|
||||
{ Clic.name = "signer" ;
|
||||
title = "Commands specific to the signing daemon" }
|
||||
|
||||
let commands =
|
||||
let commands base_dir require_auth =
|
||||
Client_keys_commands.commands () @
|
||||
[ command ~group
|
||||
~desc: "Launch a signer daemon over a TCP socket."
|
||||
@ -63,7 +63,7 @@ let commands =
|
||||
(prefixes [ "launch" ; "socket" ; "signer" ] @@ stop)
|
||||
(fun (host, port) cctxt ->
|
||||
Tezos_signer_backends.Encrypted.decrypt_all cctxt >>=? fun () ->
|
||||
Socket_daemon.run cctxt (Tcp (host, port))) ;
|
||||
Socket_daemon.run cctxt (Tcp (host, port)) ~require_auth) ;
|
||||
command ~group
|
||||
~desc: "Launch a signer daemon over a local Unix socket."
|
||||
(args1
|
||||
@ -72,12 +72,12 @@ let commands =
|
||||
~short: 's'
|
||||
~long: "socket"
|
||||
~placeholder: "path"
|
||||
~default: default_unix_path
|
||||
~default: (Filename.concat base_dir "socket")
|
||||
(parameter (fun _ s -> return s))))
|
||||
(prefixes [ "launch" ; "local" ; "signer" ] @@ stop)
|
||||
(fun path cctxt ->
|
||||
Tezos_signer_backends.Encrypted.decrypt_all cctxt >>=? fun () ->
|
||||
Socket_daemon.run cctxt (Unix path)) ;
|
||||
Socket_daemon.run cctxt (Unix path) ~require_auth) ;
|
||||
command ~group
|
||||
~desc: "Launch a signer daemon over HTTPS."
|
||||
(args2
|
||||
@ -109,9 +109,31 @@ let commands =
|
||||
(parameter (fun _ s -> return s)) @@ stop)
|
||||
(fun (host, port) cert key cctxt ->
|
||||
Tezos_signer_backends.Encrypted.decrypt_all cctxt >>=? fun () ->
|
||||
Https_daemon.run cctxt ~host ~port ~cert ~key) ;
|
||||
Https_daemon.run cctxt ~host ~port ~cert ~key ~require_auth) ;
|
||||
command ~group
|
||||
~desc: "Authorize a given public key to perform signing requests."
|
||||
(args1
|
||||
(arg
|
||||
~doc: "an optional name for the key (defaults to the hash)"
|
||||
~short: 'N'
|
||||
~long: "name"
|
||||
~placeholder: "name"
|
||||
(parameter (fun _ s -> return s))))
|
||||
(prefixes [ "add" ; "authorized" ; "key" ] @@
|
||||
param
|
||||
~name:"pk"
|
||||
~desc: "full public key (Base58 encoded)"
|
||||
(parameter (fun _ s -> Lwt.return (Signature.Public_key.of_b58check s))) @@
|
||||
stop)
|
||||
(fun name key cctxt ->
|
||||
let pkh = Signature.Public_key.hash key in
|
||||
let name = match name with
|
||||
| Some name -> name
|
||||
| None -> Signature.Public_key_hash.to_b58check pkh in
|
||||
Handler.Authorized_key.add ~force:false cctxt name key)
|
||||
]
|
||||
|
||||
|
||||
let home = try Sys.getenv "HOME" with Not_found -> "/root"
|
||||
|
||||
let default_base_dir =
|
||||
@ -132,9 +154,17 @@ let base_dir_arg () =
|
||||
By default: '" ^ default_base_dir ^"'.")
|
||||
(string_parameter ())
|
||||
|
||||
let require_auth_arg () =
|
||||
switch
|
||||
~long:"require-authentication"
|
||||
~short:'A'
|
||||
~doc:"Require a signature from the caller to sign."
|
||||
()
|
||||
|
||||
let global_options () =
|
||||
args1
|
||||
args2
|
||||
(base_dir_arg ())
|
||||
(require_auth_arg ())
|
||||
|
||||
(* Main (lwt) entry *)
|
||||
let main () =
|
||||
@ -158,7 +188,7 @@ let main () =
|
||||
begin
|
||||
begin
|
||||
parse_global_options
|
||||
(global_options ()) () original_args >>=? fun (base_dir, remaining) ->
|
||||
(global_options ()) () original_args >>=? fun ((base_dir, require_auth), remaining) ->
|
||||
let base_dir = Option.unopt ~default:default_base_dir base_dir in
|
||||
let cctxt = object
|
||||
inherit Client_context_unix.unix_logger ~base_dir
|
||||
@ -177,7 +207,7 @@ let main () =
|
||||
~global_options:(global_options ())
|
||||
(if Unix.isatty Unix.stdout then Clic.Ansi else Clic.Plain)
|
||||
Format.std_formatter
|
||||
commands in
|
||||
(commands base_dir require_auth) in
|
||||
begin match autocomplete with
|
||||
| Some (prev_arg, cur_arg, script) ->
|
||||
Clic.autocompletion
|
||||
|
@ -11,7 +11,7 @@ open Signer_messages
|
||||
|
||||
let log = Signer_logging.lwt_log_notice
|
||||
|
||||
let run (cctxt : #Client_context.wallet) path =
|
||||
let run (cctxt : #Client_context.wallet) path ~require_auth =
|
||||
Lwt_utils_unix.Socket.bind path >>=? fun fd ->
|
||||
let rec loop () =
|
||||
Lwt_unix.accept fd >>= fun (fd, _) ->
|
||||
@ -19,7 +19,7 @@ let run (cctxt : #Client_context.wallet) path =
|
||||
Lwt_utils_unix.Socket.recv fd Request.encoding >>=? function
|
||||
| Sign req ->
|
||||
let encoding = result_encoding Sign.Response.encoding in
|
||||
Handler.sign cctxt req.pkh req.data >>= fun res ->
|
||||
Handler.sign cctxt req ~require_auth >>= fun res ->
|
||||
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||
Lwt_unix.close fd >>= fun () ->
|
||||
return ()
|
||||
@ -29,6 +29,17 @@ let run (cctxt : #Client_context.wallet) path =
|
||||
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||
Lwt_unix.close fd >>= fun () ->
|
||||
return ()
|
||||
| Authorized_keys ->
|
||||
let encoding = result_encoding Authorized_keys.Response.encoding in
|
||||
begin if require_auth then
|
||||
Handler.Authorized_key.load cctxt >>=? fun keys ->
|
||||
return (Authorized_keys.Response.Authorized_keys
|
||||
(keys |> List.split |> snd |> List.map Signature.Public_key.hash))
|
||||
else return Authorized_keys.Response.No_authentication
|
||||
end >>= fun res ->
|
||||
Lwt_utils_unix.Socket.send fd encoding res >>= fun _ ->
|
||||
Lwt_unix.close fd >>= fun () ->
|
||||
return ()
|
||||
end ;
|
||||
loop ()
|
||||
in
|
||||
|
@ -9,4 +9,6 @@
|
||||
|
||||
val run:
|
||||
#Client_context.io_wallet ->
|
||||
Lwt_utils_unix.Socket.addr -> 'a tzresult Lwt.t
|
||||
Lwt_utils_unix.Socket.addr ->
|
||||
require_auth: bool ->
|
||||
'a tzresult Lwt.t
|
||||
|
@ -74,18 +74,6 @@ let main select_commands =
|
||||
ignore Clic.(setup_formatter Format.err_formatter
|
||||
(if Unix.isatty Unix.stderr then Ansi else Plain) Short) ;
|
||||
init_logger () >>= fun () ->
|
||||
Client_keys.register_signer
|
||||
(module Tezos_signer_backends.Unencrypted) ;
|
||||
Client_keys.register_signer
|
||||
(module Tezos_signer_backends.Encrypted.Make(struct
|
||||
let cctxt = new Client_context_unix.unix_prompter
|
||||
end)) ;
|
||||
Client_keys.register_signer
|
||||
(module Tezos_signer_backends.Https) ;
|
||||
Client_keys.register_signer
|
||||
(module Tezos_signer_backends.Socket.Unix) ;
|
||||
Client_keys.register_signer
|
||||
(module Tezos_signer_backends.Socket.Tcp) ;
|
||||
Lwt.catch begin fun () -> begin
|
||||
Client_config.parse_config_args
|
||||
(new unix_full
|
||||
@ -102,14 +90,6 @@ let main select_commands =
|
||||
tls = parsed_config_file.tls ;
|
||||
} in
|
||||
let ctxt = new RPC_client.http_ctxt rpc_config Media_type.all_media_types in
|
||||
select_commands ctxt parsed_args >>=? fun commands ->
|
||||
let commands =
|
||||
Clic.add_manual
|
||||
~executable_name
|
||||
~global_options
|
||||
(if Unix.isatty Unix.stdout then Clic.Ansi else Clic.Plain)
|
||||
Format.std_formatter
|
||||
(config_commands @ builtin_commands @ commands) in
|
||||
let rpc_config =
|
||||
if parsed_args.print_timings then
|
||||
{ rpc_config with
|
||||
@ -124,12 +104,48 @@ let main select_commands =
|
||||
~confirmations:parsed_args.confirmations
|
||||
~base_dir:parsed_config_file.base_dir
|
||||
~rpc_config:rpc_config in
|
||||
Client_keys.register_signer
|
||||
(module Tezos_signer_backends.Unencrypted) ;
|
||||
Client_keys.register_signer
|
||||
(module Tezos_signer_backends.Encrypted.Make(struct
|
||||
let cctxt = (client_config :> Client_context.prompter)
|
||||
end)) ;
|
||||
let module Remote_authenticator = struct
|
||||
let authenticate pkhs payload =
|
||||
Client_keys.list_keys client_config >>=? fun keys ->
|
||||
match List.filter_map
|
||||
(function
|
||||
| (_, known_pkh, _, Some known_sk_uri)
|
||||
when List.exists (fun pkh -> Signature.Public_key_hash.equal pkh known_pkh) pkhs ->
|
||||
Some known_sk_uri
|
||||
| _ -> None)
|
||||
keys with
|
||||
| sk_uri :: _ ->
|
||||
Client_keys.sign sk_uri payload
|
||||
| [] -> failwith
|
||||
"remote signer expects authentication signature, \
|
||||
but no authorized key was found in the wallet"
|
||||
end in
|
||||
let module Https = Tezos_signer_backends.Https.Make(Remote_authenticator) in
|
||||
let module Socket = Tezos_signer_backends.Socket.Make(Remote_authenticator) in
|
||||
Client_keys.register_signer (module Https) ;
|
||||
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
|
||||
end))
|
||||
end ;
|
||||
select_commands ctxt parsed_args >>=? fun commands ->
|
||||
let commands =
|
||||
Clic.add_manual
|
||||
~executable_name
|
||||
~global_options
|
||||
(if Unix.isatty Unix.stdout then Clic.Ansi else Clic.Plain)
|
||||
Format.std_formatter
|
||||
(config_commands @ builtin_commands @ commands) in
|
||||
begin match autocomplete with
|
||||
| Some (prev_arg, cur_arg, script) ->
|
||||
Clic.autocompletion
|
||||
|
@ -11,6 +11,12 @@ 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."
|
||||
|
||||
@ -56,7 +62,22 @@ let sign ?watermark uri msg =
|
||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||
RPC_client.call_service
|
||||
Media_type.all_media_types
|
||||
~base Signer_services.sign ((), pkh) () msg
|
||||
~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 ()
|
||||
|
@ -7,6 +7,9 @@
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
include Client_keys.SIGNER
|
||||
module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
end)
|
||||
: Client_keys.SIGNER
|
||||
|
||||
val make_base: string -> int -> Uri.t
|
||||
|
@ -11,7 +11,10 @@ open Client_keys
|
||||
|
||||
let scheme = "remote"
|
||||
|
||||
module Make(S : sig val default : Uri.t end) = struct
|
||||
module Make(S : sig
|
||||
val default : Uri.t
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
end) = struct
|
||||
|
||||
let scheme = scheme
|
||||
|
||||
@ -27,6 +30,9 @@ module Make(S : sig val default : Uri.t end) = struct
|
||||
- $TEZOS_SIGNER_TCP_HOST and $TEZOS_SIGNER_TCP_PORT (default: 7732),\n\
|
||||
- $TEZOS_SIGNER_HTTPS_HOST and $TEZOS_SIGNER_HTTPS_PORT (default: 443)."
|
||||
|
||||
module Socket = Socket.Make(S)
|
||||
module Https = Https.Make(S)
|
||||
|
||||
let get_remote () =
|
||||
match Uri.scheme S.default with
|
||||
| Some "unix" -> (module Socket.Unix : SIGNER)
|
||||
|
@ -7,7 +7,10 @@
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
module Make(S : sig val default : Uri.t end) : Client_keys.SIGNER
|
||||
module Make(S : sig
|
||||
val default : Uri.t
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
end) : Client_keys.SIGNER
|
||||
|
||||
val make_pk: Signature.public_key -> Client_keys.pk_uri
|
||||
val make_sk: Signature.secret_key -> Client_keys.sk_uri
|
||||
|
@ -10,18 +10,36 @@
|
||||
open Client_keys
|
||||
open Signer_messages
|
||||
|
||||
let tcp_scheme = "tcp"
|
||||
let unix_scheme = "unix"
|
||||
|
||||
module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
end) = struct
|
||||
|
||||
let sign ?watermark path pkh msg =
|
||||
let msg =
|
||||
match watermark with
|
||||
| None -> msg
|
||||
| Some watermark ->
|
||||
MBytes.concat "" [ Signature.bytes_of_watermark watermark ; msg ] in
|
||||
let req = { Sign.Request.pkh ; data = msg } in
|
||||
Lwt_utils_unix.Socket.connect path >>=? fun conn ->
|
||||
Lwt_utils_unix.Socket.send
|
||||
conn Request.encoding Request.Authorized_keys >>=? fun () ->
|
||||
Lwt_utils_unix.Socket.recv conn
|
||||
Authorized_keys.Response.encoding >>=? fun authorized_keys ->
|
||||
begin match authorized_keys with
|
||||
| No_authentication -> return None
|
||||
| Authorized_keys authorized_keys ->
|
||||
P.authenticate authorized_keys
|
||||
(Sign.Request.to_sign ~pkh ~data:msg) >>=? fun signature ->
|
||||
return (Some signature)
|
||||
end >>=? fun signature ->
|
||||
let req = { Sign.Request.pkh ; data = msg ; signature } in
|
||||
Lwt_utils_unix.Socket.send
|
||||
conn Request.encoding (Request.Sign req) >>=? fun () ->
|
||||
let encoding = result_encoding Sign.Response.encoding in
|
||||
Lwt_utils_unix.Socket.recv conn encoding >>=? fun res ->
|
||||
Lwt_utils_unix.Socket.recv conn
|
||||
(result_encoding Sign.Response.encoding) >>=? fun res ->
|
||||
Lwt_unix.close conn >>= fun () ->
|
||||
Lwt.return res
|
||||
|
||||
@ -36,7 +54,7 @@ let public_key path pkh =
|
||||
|
||||
module Unix = struct
|
||||
|
||||
let scheme = "unix"
|
||||
let scheme = unix_scheme
|
||||
|
||||
let title =
|
||||
"Built-in tezos-signer using remote signer through hardcoded unix socket."
|
||||
@ -72,7 +90,7 @@ end
|
||||
|
||||
module Tcp = struct
|
||||
|
||||
let scheme = "tcp"
|
||||
let scheme = tcp_scheme
|
||||
|
||||
let title =
|
||||
"Built-in tezos-signer using remote signer through hardcoded tcp socket."
|
||||
@ -110,8 +128,11 @@ module Tcp = struct
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
let make_unix_base path =
|
||||
Uri.make ~scheme:Unix.scheme ~path ()
|
||||
Uri.make ~scheme:unix_scheme ~path ()
|
||||
|
||||
let make_tcp_base host port =
|
||||
Uri.make ~scheme:Tcp.scheme ~host ~port ()
|
||||
Uri.make ~scheme:tcp_scheme ~host ~port ()
|
||||
|
@ -7,8 +7,12 @@
|
||||
(* *)
|
||||
(**************************************************************************)
|
||||
|
||||
module Make(P : sig
|
||||
val authenticate: Signature.Public_key_hash.t list -> MBytes.t -> Signature.t tzresult Lwt.t
|
||||
end) : sig
|
||||
module Unix : Client_keys.SIGNER
|
||||
module Tcp : Client_keys.SIGNER
|
||||
end
|
||||
|
||||
val make_unix_base: string -> Uri.t
|
||||
val make_tcp_base: string -> int -> Uri.t
|
||||
|
@ -14,18 +14,26 @@ module Sign = struct
|
||||
type t = {
|
||||
pkh: Signature.Public_key_hash.t ;
|
||||
data: MBytes.t ;
|
||||
signature: Signature.t option ;
|
||||
}
|
||||
|
||||
let to_sign ~pkh ~data =
|
||||
MBytes.concat ""
|
||||
[ MBytes.of_hex (`Hex "04") ;
|
||||
Signature.Public_key_hash.to_bytes pkh ;
|
||||
data ]
|
||||
|
||||
let encoding =
|
||||
let open Data_encoding in
|
||||
conv
|
||||
(fun { pkh ; data } ->
|
||||
(pkh, data))
|
||||
(fun (pkh, data) ->
|
||||
{ pkh ; data })
|
||||
(obj2
|
||||
(fun { pkh ; data ; signature } ->
|
||||
(pkh, data, signature))
|
||||
(fun (pkh, data, signature) ->
|
||||
{ pkh ; data ; signature })
|
||||
(obj3
|
||||
(req "pkh" Signature.Public_key_hash.encoding)
|
||||
(req "data" bytes))
|
||||
(req "data" bytes)
|
||||
(opt "signature" Signature.encoding))
|
||||
|
||||
end
|
||||
|
||||
@ -62,11 +70,38 @@ module Public_key = struct
|
||||
|
||||
end
|
||||
|
||||
module Authorized_keys = struct
|
||||
|
||||
module Response = struct
|
||||
|
||||
type t =
|
||||
| No_authentication
|
||||
| Authorized_keys of Signature.Public_key_hash.t list
|
||||
|
||||
let encoding =
|
||||
let open Data_encoding in
|
||||
union
|
||||
[ case (Tag 0)
|
||||
~title: "No_authentication"
|
||||
(constant "no_authentication_required")
|
||||
(function No_authentication -> Some () | _ -> None)
|
||||
(fun () -> No_authentication) ;
|
||||
case (Tag 1)
|
||||
~title: "Authorized_keys"
|
||||
(list Signature.Public_key_hash.encoding)
|
||||
(function Authorized_keys l -> Some l | _ -> None)
|
||||
(fun l -> Authorized_keys l) ]
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module Request = struct
|
||||
|
||||
type t =
|
||||
| Sign of Sign.Request.t
|
||||
| Public_key of Public_key.Request.t
|
||||
| Authorized_keys
|
||||
|
||||
let encoding =
|
||||
let open Data_encoding in
|
||||
@ -85,6 +120,11 @@ module Request = struct
|
||||
Public_key.Request.encoding)
|
||||
(function Public_key req -> Some ((), req) | _ -> None)
|
||||
(fun ((), req) -> Public_key req) ;
|
||||
case (Tag 2)
|
||||
~title:"Authorized_keys"
|
||||
(obj1 (req "kind" (constant "authorized_keys")))
|
||||
(function Authorized_keys -> Some () | _ -> None)
|
||||
(fun () -> Authorized_keys) ;
|
||||
]
|
||||
|
||||
end
|
||||
|
@ -13,7 +13,12 @@ module Sign : sig
|
||||
type t = {
|
||||
pkh: Signature.Public_key_hash.t ;
|
||||
data: MBytes.t ;
|
||||
signature: Signature.t option ;
|
||||
}
|
||||
val to_sign:
|
||||
pkh: Signature.Public_key_hash.t ->
|
||||
data: MBytes.t ->
|
||||
MBytes.t
|
||||
val encoding : t Data_encoding.t
|
||||
end
|
||||
|
||||
@ -38,11 +43,23 @@ module Public_key : sig
|
||||
|
||||
end
|
||||
|
||||
module Authorized_keys : sig
|
||||
|
||||
module Response : sig
|
||||
type t =
|
||||
| No_authentication
|
||||
| Authorized_keys of Signature.Public_key_hash.t list
|
||||
val encoding : t Data_encoding.t
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module Request : sig
|
||||
|
||||
type t =
|
||||
| Sign of Sign.Request.t
|
||||
| Public_key of Public_key.Request.t
|
||||
| Authorized_keys
|
||||
val encoding : t Data_encoding.t
|
||||
|
||||
end
|
||||
|
@ -8,9 +8,19 @@
|
||||
(**************************************************************************)
|
||||
|
||||
let sign =
|
||||
let query =
|
||||
let open RPC_query in
|
||||
query (fun signature -> signature)
|
||||
|+ opt_field
|
||||
~descr: "Must be provided if the signer requires \
|
||||
authentication. In this case, it must be the signature \
|
||||
of the public key hash and message concatenated, by one \
|
||||
of the keys authorized by the signer."
|
||||
"authentication" Signature.rpc_arg (fun signature -> signature)
|
||||
|> seal in
|
||||
RPC_service.post_service
|
||||
~description: "Sign a piece of data with a given remote key"
|
||||
~query: RPC_query.empty
|
||||
~query
|
||||
~input: Data_encoding.bytes
|
||||
~output: Data_encoding.(obj1 (req "signature" Signature.encoding))
|
||||
RPC_path.(root /: Signature.Public_key_hash.rpc_arg)
|
||||
@ -21,3 +31,13 @@ let public_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)
|
||||
|
||||
let authorized_keys =
|
||||
RPC_service.get_service
|
||||
~description: "Retrieve the public keys that can be used to \
|
||||
authenticate signing commands.\n\
|
||||
If the empty object is returned, the signer has \
|
||||
been set to accept unsigned commands."
|
||||
~query: RPC_query.empty
|
||||
~output: Data_encoding.(obj1 (opt "authorized_keys" (list Signature.Public_key_hash.encoding)))
|
||||
RPC_path.(root / "authorized_keys")
|
||||
|
@ -9,8 +9,12 @@
|
||||
|
||||
val sign :
|
||||
([ `POST ], unit, unit * Signature.Public_key_hash.t,
|
||||
unit, MBytes.t, Signature.t) RPC_service.t
|
||||
Signature.t option, MBytes.t, Signature.t) RPC_service.t
|
||||
|
||||
val public_key :
|
||||
([ `GET ], unit, unit * Signature.Public_key_hash.t,
|
||||
unit, unit, Signature.Public_key.t) RPC_service.t
|
||||
|
||||
val authorized_keys :
|
||||
([ `GET ], unit, unit,
|
||||
unit, unit, Signature.Public_key_hash.t list option) RPC_service.t
|
||||
|
Loading…
Reference in New Issue
Block a user