Skip to content

Instantly share code, notes, and snippets.

@Zenithar
Last active February 13, 2020 14:44
Show Gist options
  • Save Zenithar/f43ba955e4cbfb1b162d3bfc75aced96 to your computer and use it in GitHub Desktop.
Save Zenithar/f43ba955e4cbfb1b162d3bfc75aced96 to your computer and use it in GitHub Desktop.

Password Merger

Small tools to generate password and merge from a stdin given template.

Usage

From commandline

$ echo "{{ strongPassword }}" | pwmrg
9t6\?78.AZ4_w2(5rP1]VH#30K,b<Yc)

Using a complete template

http:
    cookie:
        encryption_key: "{{ customPassword 128 20 10 false false | b64 }}"
$ cat definition.yaml | pwmrg
http:
    cookie:
        encryption_key: "SnlPNyZHY11iaUljZWxVZCp5OHZ6TnR2UDZqLkRAV2hmW2lRQ1FTRkY2MDVmcUl3MEZoN00wZjZKSGlrYVJNbE5NN0B0TENMVml+dHNVaGVnbzJTYkNGR1lLSHpCcDVTZ3NpOWVqaFA3VzJBeUhQVVdJezBMMEw1RSppcHRxdjk="

From template to Vault

Consider this JSON file

{
    "cookie-secret": "{{ noSymbolPassword }}",
    "random-seed": "{{ strongPassword | json }}",
    "key-generation-root": "{{ paranoidPassword | json }}"
}

Pull the secret bundle template, merge with generated password, and publish to vault.

curl https://....../bundle.spec.json | pwmrg | vault kv put app/test/12345678912345678 -

If you need to view passwords :

$ vault kv get -format=json -field="data" app/test/12345678912345678
{
    "cookie-secret": "0FR4qR7gT7oj3oTcAIijM4e1Uc2tC4r6",
    "random-seed": "eZtV)s\\\\I1%v73=48.2do~up06m9!*\\\"5}",
    "key-generation-root": "S4v[8xDkp_HEPOT-BjnNoQrLKyFas9#ZC3tR2V]fe6lJ7qh1A+m@5\\x3Ci0YdUGb~{c"
}

No secrets stored on local provisioner machine.

Template functions

Generators

customPassword

{{ customPassword length numDigits numSymbol noUpper allowRepeat }}

  • length int : length of the generated password
  • numDigits int : digits count in generated password
  • numSymbol int : symbol count in generated password
  • noUpper bool : disable uppercase letters
  • allowRepeat bool : disable character repetition

paranoidPassword

{{ paranoidPassword }}

noSymbolPassword

Generate a 64 characters length, with 10 digits and 10 symbols, with uppercase and without repetition.

{{ noSymbolPassword }}

Generate a 64 characters length, with 20 digits without symbols, with uppercase and with repetition.

strongPassword

{{ strongPassword }}

Generate a 32 characters length, with 10 digits and 10 symbols, with uppercase and without repetition.

Transformers

b64

{{ strongPassword | b64 }}

Encode a given string using Standard Base64 encoding.

json

{{ strongPassword | json }}

Escape symbols in generated password to be compliant as a JSON string value.

html

{{ strongPassword | html }}

Escape symbols in generated password to be compliant for HTML display.

url

Escape symbols in generated password to be compliant for URL usages.

{{ strongPassword | url }}

package main
import (
"encoding/base64"
"fmt"
"io/ioutil"
"log"
"os"
"text/template"
"github.com/sethvargo/go-password/password"
)
// -----------------------------------------------------------------------------
func tmplPassword(length, numDigits, numSymbol int, noUpper, allowRepeat bool) (string, error) {
p, err := password.Generate(length, numDigits, numSymbol, noUpper, allowRepeat)
if err != nil {
return "", fmt.Errorf("unable to generate a password: %v", err)
}
return p, nil
}
func tmplParanoid() (string, error) {
return tmplPassword(64, 10, 10, false, false)
}
func tmplNoSymbol() (string, error) {
return tmplPassword(32, 10, 0, false, true)
}
func tmplStrong() (string, error) {
return tmplPassword(32, 10, 10, false, false)
}
func tmplBase64Encode(v string) (string, error) {
return base64.StdEncoding.EncodeToString([]byte(v)), nil
}
func tmplJSONEscape(v string) string {
return template.JSEscapeString(template.JSEscapeString(v))
}
// -----------------------------------------------------------------------------
func main() {
// Read all content from stdin
content, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("reading: %s", err)
}
// Register render functions
funcMap := template.FuncMap{
"customPassword": tmplPassword,
"paranoidPassword": tmplParanoid,
"noSymbolPassword": tmplNoSymbol,
"strongPassword": tmplStrong,
"b64": tmplBase64Encode,
"json": tmplJSONEscape,
"html": template.HTMLEscapeString,
"url": template.URLQueryEscaper,
}
// Compile input as text template
tmpl, err := template.New("input").Funcs(funcMap).Parse(string(content))
if err != nil {
log.Fatalf("parsing: %s", err)
}
// Execute template
err = tmpl.Execute(os.Stdout, nil)
if err != nil {
log.Fatalf("execution: %s", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment