@@ -15,61 +15,6 @@ type output_mode =
1515
1616let verbose_eprintlf ?(verbose = false ) fmt = if verbose then Devkit. eprintfn fmt else ksprintf (Fun. const () ) fmt
1717
18- module Edit = struct
19- let new_secret_recipients_notice =
20- {|
21- If you are adding a new secret in a new folder, please keep recipients to a minimum and include the following :
22- - @root
23- - yourself
24- - people who help manage the secret , or people who would have access to it anyway
25- - people who need access to do their job
26- - servers /clusters that will consume the secret
27-
28- If the secret is a staging secret , its only recipient should be @everyone .
29- |}
30-
31- let show_recipients_notice_if_true cond = if cond then prerr_endline new_secret_recipients_notice
32-
33- let edit_secret ?(self_fallback = false ) ?(verbose = false ) secret_name ~allow_retry ~get_updated_secret =
34- let raw_secret_name = show_name secret_name in
35- let original_secret =
36- match Storage.Secrets. secret_exists secret_name with
37- | false -> None
38- | true ->
39- try Devkit. some @@ Storage.Secrets. decrypt_exn secret_name
40- with exn -> Shell. die ~exn " E: failed to decrypt %s" raw_secret_name
41- in
42- try
43- let updated_secret = get_updated_secret original_secret in
44- match updated_secret, original_secret with
45- | Ok updated_secret , Some original_secret when updated_secret = original_secret ->
46- prerr_endline " I: secret unchanged"
47- | Error e , _ -> Shell. die " E: %s" e
48- | Ok updated_secret , _ ->
49- let secret_path = path_of_secret_name secret_name in
50- let secret_recipients' = Storage.Secrets. get_recipients_from_path_exn secret_path in
51- let secret_recipients =
52- if secret_recipients' = [] && self_fallback then (
53- let own_recipients = Storage.Secrets. recipients_of_own_id () in
54- let () = Commands.Recipients. add_recipients_if_none_exists own_recipients secret_path in
55- Storage.Secrets. get_recipients_from_path_exn secret_path)
56- else secret_recipients'
57- in
58- if secret_recipients = [] then Exn. fail " E: no recipients specified for this secret"
59- else (
60- let is_first_secret_in_new_folder = Option. is_none original_secret && secret_recipients' = [] in
61- match allow_retry with
62- | true ->
63- show_recipients_notice_if_true is_first_secret_in_new_folder;
64- Retry. encrypt_with_retry ~plaintext: updated_secret ~secret_name secret_recipients
65- | false ->
66- try
67- show_recipients_notice_if_true is_first_secret_in_new_folder;
68- Storage.Secrets. encrypt_exn ~verbose ~plaintext: updated_secret ~secret_name secret_recipients
69- with exn -> Exn. fail ~exn " E: encrypting %s failed" raw_secret_name)
70- with Failure s -> Shell. die " %s" s
71- end
72-
7318module Converters = struct
7419 let secret_arg =
7520 let parse secret_name = try Ok (Storage.Secrets. build_secret_name secret_name) with Failure s -> Error (`Msg s) in
@@ -179,43 +124,24 @@ module Rm_who = struct
179124end
180125
181126module Create = struct
182- let create_new_secret_from_stdin verbose secret_name comment_opt =
183- let create_new_secret verbose secret_name =
184- Edit. edit_secret secret_name ~verbose ~self_fallback: true ~allow_retry: false ~get_updated_secret: (fun _ ->
185- let () = input_help_if_user_input () in
186- match get_valid_input_from_stdin_exn () with
187- | Error e -> Shell. die " E: %s" e
188- | Ok plaintext_secret ->
189- let parsed_secret = Secret.Validation. parse_exn plaintext_secret in
190- let comment =
191- match comment_opt, parsed_secret.comments with
192- | Some comment , None | None , Some comment -> comment
193- | None , None -> " "
194- | Some _ , Some _ ->
195- Shell. die
196- " E: secret text already contains comments. Either use the secret text with comments or use the \
197- --comment flag."
198- in
199- (match Validation. validate_comments comment with
200- | Error e -> Shell. die " E: invalid comment format: %s" e
201- | Ok c -> Ok (reconstruct_secret ~comments: (Some c) parsed_secret)))
202- in
203- match Storage.Secrets. secret_exists secret_name with
204- | true -> Shell. die " E: refusing to create: a secret by that name already exists"
205- | false ->
127+ let create_new_secret_from_stdin ~comments secret_name =
206128 try
207- let path = Storage.Secrets. (to_path secret_name) in
208- Invariant. die_if_invariant_fails ~op_string: " create " path;
209- create_new_secret verbose secret_name
129+ match get_valid_input_from_stdin_exn () with
130+ | Error e -> Shell. die " E: %s " e
131+ | Ok plaintext_secret -> Commands.Create. add ~comments secret_name plaintext_secret
210132 with Failure s -> Shell. die " %s" s
211-
212133 let create =
213134 let doc =
214135 {| creates a new secret from stdin. If the folder doesn't have recipients specified already,
215136 tries to set them to the ones associated with \$ {PASSAGE_IDENTITY } | }
216137 in
217138 let info = Cmd. info " create" ~doc in
218- let term = Term. (const (create_new_secret_from_stdin false ) $ Flags. secret_name $ Flags. comment) in
139+ let term =
140+ Term. (
141+ const (fun secret_name comments -> create_new_secret_from_stdin ~comments secret_name)
142+ $ Flags. secret_name
143+ $ Flags. comment)
144+ in
219145 Cmd. v info term
220146end
221147
@@ -226,7 +152,8 @@ module Edit_cmd = struct
226152 Invariant. run_if_recipient ~op_string: " edit secret"
227153 ~path: Storage.Secrets. (to_path secret_name)
228154 ~f: (fun () ->
229- Edit. edit_secret secret_name ~allow_retry: true ~get_updated_secret: (fun initial ->
155+ Commands.Edit. edit_secret secret_name ~allow_retry: Retry. encrypt_with_retry
156+ ~get_updated_secret: (fun initial ->
230157 let initial_content =
231158 Option. map (fun i -> i ^ Secret. format_explainer) initial
232159 |> Option. value ~default: Secret. format_explainer
@@ -273,7 +200,7 @@ module Edit_comments = struct
273200 | None , true -> prerr_endline " I: comments unchanged"
274201 | Some old , false when old = new_comments -> prerr_endline " I: comments unchanged"
275202 | _ ->
276- let updated_secret = reconstruct_secret ~comments: ( Some new_comments) parsed_secret in
203+ let updated_secret = reconstruct_secret ~comments: new_comments parsed_secret in
277204 let secret_recipients = Util.Recipients. get_recipients_or_die secret_name in
278205 (try Retry. encrypt_with_retry ~plaintext: updated_secret ~secret_name secret_recipients
279206 with exn -> Shell. die ~exn " E: encrypting %s failed" (show_name secret_name)))
@@ -468,7 +395,7 @@ Checking for validity of own secrets. Use -v flag to break down per secret
468395 | Upgrade , SingleLineLegacy ->
469396 (try
470397 let parsed_secret = Secret.Validation. parse_exn secret_text in
471- let upgraded_secret = reconstruct_secret ~ comments: parsed_secret.comments parsed_secret in
398+ let upgraded_secret = reconstruct_secret ? comments:parsed_secret.comments parsed_secret in
472399 let recipients = Util.Recipients. get_recipients_or_die secret_name in
473400 Storage.Secrets. encrypt_exn ~verbose: false ~plaintext: upgraded_secret ~secret_name recipients;
474401 Devkit. eprintfn " I: updated %s" (show_name secret_name);
@@ -515,7 +442,8 @@ module Init = struct
515442end
516443
517444module List_ = struct
518- let list_secrets path = try Commands.List_. list_secrets path with Failure s -> Shell. die " %s" s
445+ let list_secrets path =
446+ try Commands.List_. list_secrets path |> List. iter print_endline with Failure s -> Shell. die " %s" s
519447
520448 let list =
521449 let doc = " recursively list all secrets" in
@@ -531,30 +459,26 @@ module List_ = struct
531459end
532460
533461module New = struct
534- let create_new_secret verbose secret_name =
535- let () =
536- Edit. edit_secret ~verbose ~self_fallback: true secret_name ~allow_retry: true ~get_updated_secret: (fun initial ->
537- let initial_content = Option. value ~default: Secret. format_explainer initial in
538- Editor. edit_with_validation ~initial: initial_content ~validate: Validation. validate_secret () )
539- in
540- let original_recipients = Storage.Secrets. (get_recipients_from_path_exn @@ to_path secret_name) in
541- Edit. show_recipients_notice_if_true (original_recipients = [] );
542- if yesno " Edit recipients for this secret?" then edit_recipients secret_name
543-
544- let create_new_secret' secret_name =
545- if Storage.Secrets. secret_exists secret_name then
546- Shell. die " E: refusing to create: a secret by that name already exists"
547- else (
548- try
549- let path = Storage.Secrets. (to_path secret_name) in
550- let () = Invariant. die_if_invariant_fails ~op_string: " create" path in
551- create_new_secret false secret_name
552- with Failure s -> Shell. die " %s" s)
462+ let create_new_secret secret_name =
463+ try
464+ let wiz secret_name =
465+ let () =
466+ Commands.Edit. edit_secret ~self_fallback: true secret_name ~allow_retry: Retry. encrypt_with_retry
467+ ~get_updated_secret: (fun initial ->
468+ let initial_content = Option. value ~default: Secret. format_explainer initial in
469+ Editor. edit_with_validation ~initial: initial_content ~validate: Validation. validate_secret () )
470+ in
471+ let original_recipients = Storage.Secrets. (get_recipients_from_path_exn @@ to_path secret_name) in
472+ Commands.Edit. show_recipients_notice_if_true (original_recipients = [] );
473+ if yesno " Edit recipients for this secret?" then edit_recipients secret_name
474+ in
475+ Commands.Create. bare ~f: wiz secret_name
476+ with Failure s -> Shell. die " %s" s
553477
554478 let new_ =
555479 let doc = " interactive creation of a new single-line secret" in
556480 let info = Cmd. info " new" ~doc in
557- let term = Term. (const create_new_secret' $ Flags. secret_name) in
481+ let term = Term. (const create_new_secret $ Flags. secret_name) in
558482 Cmd. v info term
559483end
560484
594518module Replace = struct
595519 let replace_secret secret_name =
596520 try
597- let recipients = Util.Recipients. get_recipients_or_die secret_name in
598- Invariant. run_if_recipient ~op_string: " replace secret"
599- ~path: Storage.Secrets. (to_path secret_name)
600- ~f: (fun () ->
601- let () = input_help_if_user_input () in
602- (* We don't need to run validation for the input here since we will be replacing only the secret
603- and not the whole file *)
604- let new_secret_plaintext = In_channel. input_all stdin in
605- if new_secret_plaintext = " " then Shell. die " E: invalid input, empty secrets are not allowed." ;
606- let is_singleline_secret =
607- (* New secret is single line if doesn't have a newline character or if it has only one,
608- at the end of the first line. This input isn't supposed to follow the storage format,
609- it only contains a secret and no comments *)
610- match String. split_on_char '\n' new_secret_plaintext with
611- | [ _ ] | [ _; " " ] -> true
612- | _ -> false
613- in
614- let updated_secret =
615- match Storage.Secrets. secret_exists secret_name with
616- | false ->
617- (* if the secret doesn't exist yet, create a new secret with the right format *)
618- (match is_singleline_secret with
619- | true -> new_secret_plaintext
620- | false -> " \n\n " ^ new_secret_plaintext)
621- | true ->
622- (* if there is already a secret, recreate or replace it *)
623- let original_secret =
624- try
625- let secret_plaintext = Storage.Secrets. decrypt_exn ~silence_stderr: true secret_name in
626- Secret.Validation. parse_exn secret_plaintext
627- with _e ->
628- Shell. die
629- " E: unable to parse secret %s's format. If we proceed, the comments will be lost. Aborting. Please \
630- use the edit command to replace and fix this secret."
631- (show_name secret_name)
632- in
633- reconstruct_with_new_text ~is_singleline: is_singleline_secret ~new_text: new_secret_plaintext
634- ~existing_comments: original_secret.comments
635- in
636- try Storage.Secrets. encrypt_exn ~verbose: false ~plaintext: updated_secret ~secret_name recipients
637- with exn -> Shell. die ~exn " E: encrypting %s failed" (show_name secret_name))
521+ let () = input_help_if_user_input () in
522+ Commands.Replace. replace_secret secret_name (In_channel. input_all stdin)
638523 with Failure s -> Shell. die " %s" s
639524
640525 let replace =
@@ -650,29 +535,11 @@ end
650535module Replace_comments = struct
651536 let replace_comment secret_name =
652537 try
653- let secret_name_str = show_name secret_name in
654- let recipients = Util.Recipients. get_recipients_or_die secret_name in
655- Invariant. run_if_recipient ~op_string: " replace comments"
656- ~path: Storage.Secrets. (to_path secret_name)
657- ~f: (fun () ->
658- match Storage.Secrets. secret_exists secret_name with
659- | false -> Shell. die " E: no such secret: %s" secret_name_str
660- | true ->
661- let original_secret =
662- try decrypt_and_parse ~silence_stderr: true secret_name
663- with _e ->
664- Shell. die
665- " E: unable to parse secret %s's format. Please fix it before replacing the comments,or use the edit \
666- command"
667- secret_name_str
668- in
669- let new_comments =
670- get_comments ?initial:original_secret.comments
671- ~help_message: " Please type the new comments and then do Ctrl+d twice to terminate input" ()
672- in
673- let updated_secret = reconstruct_secret ~comments: (Some new_comments) original_secret in
674- (try Storage.Secrets. encrypt_exn ~verbose: false ~plaintext: updated_secret ~secret_name recipients
675- with exn -> Shell. die ~exn " E: encrypting %s failed" secret_name_str))
538+ let get_new_comments original_comments =
539+ get_comments ?initial:original_comments
540+ ~help_message: " Please type the new comments and then do Ctrl+d twice to terminate input" ()
541+ in
542+ Commands.Replace. replace_comment secret_name get_new_comments
676543 with Failure s -> Shell. die " %s" s
677544
678545 let replace_comments =
@@ -688,16 +555,8 @@ module Rm = struct
688555 Arg. (value & flag & info [ " f" ; " force" ] ~doc )
689556
690557 let rm_secrets verbose paths force =
691- let rm_result ~path ~force =
692- let is_directory = Path. is_directory (Path. abs path) in
693- let string_path = show_path path in
694- if force then Storage.Secrets. rm ~is_directory path
695- else (
696- match yesno_tty_check (sprintf " Are you sure you want to delete %s?" string_path) with
697- | NoTTY | TTY true -> Storage.Secrets. rm ~is_directory path
698- | TTY false -> Storage.Secrets. Skipped )
699- in
700- try Commands.Rm. rm_secrets ~verbose ~paths ~force ~f: rm_result with Failure s -> Shell. die " %s" s
558+ let confirm ~path = yesno (sprintf " Are you sure you want to delete %s?" (show_path path)) in
559+ try Commands.Rm. rm_secrets ~verbose ~paths ~force ~confirm () with Failure s -> Shell. die " %s" s
701560
702561 let rm =
703562 let doc = " remove a secret or a folder and its secrets" in
0 commit comments