package passage
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Passage - used to store and manage access to shared secrets
Install
dune-project
Dependency
Authors
Maintainers
Sources
passage-0.3.3.tbz
sha256=2f1881583faa719031711b4fe956ef2cdcff0be2334e343a76cd719a54eec2e3
sha512=7ffbf71ddc5c5de5a65b2050dae973294f49131dceca640f878ca020d8fba3623844cd70b0f8c8c86a52af2f645c62649d0c0e8a051c95ca26c89db03877e326
doc/src/passage/secret.ml.html
Source file secret.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166type kind = | Singleline | Multiline type t = { kind : kind; text : string; comments : string option; } let kind_to_string k = match k with | Singleline -> "single-line" | Multiline -> "multi-line" let singleline_from_text_description text description = let text = String.trim text in match description with | "" -> text | _ -> Printf.sprintf "%s\n\n%s" text description let multiline_from_text_description text description = let text = String.trim text in let description = String.trim description in match description with | "" -> Printf.sprintf "\n\n%s" text | _ -> Printf.sprintf "\n%s\n\n%s" description text let format_explainer = {| # Secrets and comments formats: # (multi-line comments _should not_ have empty lines in them) # # Single line secret with commments format: # secret one line # <empty line> # comments until end of file # # Single line secret without commments format: # secret one line # # Multiline secret with comments format: # <empty line> # possibly several lines of comments # <empty line> # secret until end of file # # Multiline secret without comments format: # <empty line> # <empty line> # secret until end of file |} module Validation = struct type validation_error = | SingleLineLegacy | MultilineEmptySecret | EmptySecret | InvalidFormat let validate plaintext = if String.trim plaintext = "" then Error ("empty secrets are not allowed", EmptySecret) else ( (* We can only use String.trim on the individual lines as we'd be stripping out leading empty lines, thus missing multi-line secrets due to the format spec. We need to use String.trim below on each line read to make sure that we don't have spaces or other whitespace characters in lines that might lead to false negatives *) let lines = String.split_on_char '\n' plaintext in match lines with (* multi-line with comments *) | "" :: comment :: rest when String.trim comment <> "" -> (* find the empty line that introduces the secret and make sure that it has content *) let secret, _is_secret = List.fold_left (fun (secret, is_secret) line -> match is_secret, String.trim line with | true, s when s <> "" -> line :: secret, true | true, _ -> secret, true | false, "" -> secret, true | false, _ -> secret, false) ([], false) rest in if secret = [] then Error ("multiline: empty secret", MultilineEmptySecret) else Ok Multiline (* multi-line without comments *) | "" :: "" :: secret :: _ when String.trim secret <> "" -> Ok Multiline (* single-line with comments *) | secret :: "" :: comments when String.trim secret <> "" -> let has_empty_lines_in_cmts = match comments with | [] -> false | cmts -> String.concat "\n" cmts |> String.trim |> String.split_on_char '\n' |> List.map String.trim |> List.mem "" in (match has_empty_lines_in_cmts with | true -> Error ("empty lines are not allowed in comments", InvalidFormat) | false -> Ok Singleline) (* We don't want to allow the creation of new secrets in legacy single-line format *) | secret :: comment :: _ when String.trim secret <> "" && String.trim comment <> "" -> Error ( "single-line secrets with comments should have an empty line between the secret and the comments.", SingleLineLegacy ) (* single-line without comments *) | [ secret ] when String.trim secret <> "" -> Ok Singleline | _ -> Error ("invalid format", InvalidFormat)) (** {v Multiline secret with comments format: <empty line> possibly several lines of comments without empty lines <empty line> secret until end of file Multiline secret without comments format: <empty line> <empty line> secret until end of file Single line secret with commments format: secret one line <empty line> comments until end of file Single line secret without commments format: secret one line Single line secret with commments legacy format [DEPRECATED]: secret one line comments until the end of file v} *) let parse_exn plaintext_content = if String.trim plaintext_content = "" then failwith "empty secrets are not allowed"; let lines = String.split_on_char '\n' plaintext_content in let to_comments_format comments = match comments with | [] -> None | _ -> Some (comments |> String.concat "\n" |> String.trim) in match lines with | "" :: tl -> (* multi-line secret *) let text, comments_lines, (_ : bool) = List.fold_left (fun (secret_text, comments, is_secret) line -> match is_secret, line with | true, _ -> line :: secret_text, comments, true | false, "" -> secret_text, comments, true | false, s -> secret_text, s :: comments, false) ([], [], false) tl in let text = List.rev text |> String.concat "\n" |> String.trim in if text = "" then failwith "broken format multi-line secret (empty secret text). Please fix secret." else { kind = Multiline; text; comments = to_comments_format (List.rev comments_lines) } (* We keep the second pattern to match legacy secrets, which didn't have an empty line to separate from comments *) | text :: "" :: comments_lines | text :: comments_lines -> (* single line secret *) { kind = Singleline; text; comments = to_comments_format comments_lines } | [] -> failwith "empty secrets are not allowed" let validity_to_string name secret_text = match validate secret_text with | Ok kind -> Printf.sprintf "✅ %s [ valid %s ]" name (kind_to_string kind) | Error (e, _typ) -> Printf.sprintf "❌ %s Invalid format: %s" name e end
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>