-
-
Save consideRatio/1c42cc9f07a7545cb81ec98219629f15 to your computer and use it in GitHub Desktop.
{{/* | |
Returns given number of random Hex characters. | |
In practice, it generates up to 100 randAlphaNum strings | |
that are filtered from non-hex characters and augmented | |
to the resulting string that is finally trimmed down. | |
*/}} | |
{{- define "jupyterhub.randHex" -}} | |
{{- $result := "" }} | |
{{- range $i := until 100 }} | |
{{- if lt (len $result) . }} | |
{{- $rand_list := randAlphaNum . | splitList "" -}} | |
{{- $reduced_list := without $rand_list "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" }} | |
{{- $rand_string := join "" $reduced_list }} | |
{{- $result = print $result $rand_string -}} | |
{{- end }} | |
{{- end }} | |
{{- $result | trunc . }} | |
{{- end }} |
Thanks for sharing @giuliocalzolari! This is what the open-source project I contribute to ended up doing:
{{- /*
Returns given number of random Hex characters.
- randNumeric 4 | atoi generates a random number in [0, 10^4)
This is a range range evenly divisble by 16, but even if off by one,
that last partial interval offsetting randomness is only 1 part in 625.
- mod N 16 maps to the range 0-15
- printf "%x" represents a single number 0-15 as a single hex character
*/}}
{{- define "jupyterhub.randHex" -}}
{{- $result := "" }}
{{- range $i := until . }}
{{- $rand_hex_char := mod (randNumeric 4 | atoi) 16 | printf "%x" }}
{{- $result = print $result $rand_hex_char }}
{{- end }}
{{- $result }}
{{- end }}
About persisting generated credentials between helm chart upgrade
If Helm templates are used to generate a key like this, one may run into issues when they are re-generated on the next helm upgrade
. Ideally they would be re-used instead.
This is possible, and done in practice by the JupyterHub Helm chart, thanks to the lookup
function. See for example a helper function to generate some credentials and where its used to set the value of a key in a k8s Secret managed by the Helm chart.
If I may add my own suggestion to the conversation... Here is, in my opinion, an even simpler way of doing it (no loops, no modulo, no filtering or shuffling).
{{/*
Generate an hexadecimal secret of given length.
Usage: {{ my-functions.randHex 64 }}
Process:
- Generate ceil(targetLength/2) random bytes using randAscii.
- Display as hexadecimal; as a byte is written with two hexadecimal digits, we have an output of size 2*ceil(targetLength/2).
- This means that for odd numbers we have one byte too many. So we just truncate the size of our output to $length, and voilà!
*/}}
{{- define "my-functions.randHex" -}}
{{- $length := . }}
{{- if or (not (kindIs "int" $length)) (le $length 0) }}
{{- printf "my-functions.randHex expects a positive integer (%d passed)" $length | fail }}
{{- end}}
{{- printf "%x" (randAscii (divf $length 2 | ceil | int)) | trunc $length }}
{{- end}}
@gjorando: This is not optimal, because randAscii does not generate all possible bytes from 0x00 to 0xFF, so the result has lower entropy than the other solutions mentioned here.
28 random hex digits can be easily generated using {{ regexReplaceAll "-." uuidv4 "" }}
. This removes digits directly following a hyphen, because some of them have reduced entropy (constant 4, or 8 to b). This can be embedded in a loop to produce more than 28 digits. The end result can be cut to a specific length with substr
.
different approach using shuffle