diff --git a/Makefile b/Makefile index 8387900..09a216f 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,8 @@ run: deps : $(GOGET) -v ./... -install : - ./keys.sh +install : build + cmd/writefreely/$(BINARY_NAME) --gen-keys cd less/; $(MAKE) install $(MFLAGS) ui : force_look diff --git a/README.md b/README.md index 0393695..570b3ea 100644 --- a/README.md +++ b/README.md @@ -52,8 +52,8 @@ mysql -u YOURUSERNAME -p writefreely < schema.sql # 3) Configure your blog ./writefreely --config -# 4) Generate data encryption keys (especially for production) -./keys.sh +# 4) Generate data encryption keys +./writefreely --gen-keys # 5) Run ./writefreely @@ -79,9 +79,7 @@ Ready to hack on your site? Here's a quick overview. go get github.com/writeas/writefreely/cmd/writefreely ``` -Create your database, import the schema, and configure your site [as shown above](#quick-start). - -Now generate the CSS: +Create your database, import the schema, and configure your site [as shown above](#quick-start). Then generate the remaining files you'll need: ```bash make install # Generates encryption keys; installs LESS compiler diff --git a/app.go b/app.go index c50d0db..635c2f6 100644 --- a/app.go +++ b/app.go @@ -124,6 +124,7 @@ func Serve() { debugPtr := flag.Bool("debug", false, "Enables debug logging.") createConfig := flag.Bool("create-config", false, "Creates a basic configuration and exits") doConfig := flag.Bool("config", false, "Run the configuration process") + genKeys := flag.Bool("gen-keys", false, "Generate encryption and authentication keys") flag.Parse() debugging = *debugPtr @@ -167,6 +168,23 @@ func Serve() { log.Info("Done!") } os.Exit(0) + } else if *genKeys { + errStatus := 0 + + err := generateKey(emailKeyPath) + if err != nil { + errStatus = 1 + } + err = generateKey(cookieAuthKeyPath) + if err != nil { + errStatus = 1 + } + err = generateKey(cookieKeyPath) + if err != nil { + errStatus = 1 + } + + os.Exit(errStatus) } log.Info("Initializing...") diff --git a/keys.go b/keys.go index 7058111..b5d8ede 100644 --- a/keys.go +++ b/keys.go @@ -1,12 +1,17 @@ package writefreely import ( + "crypto/rand" + "github.com/writeas/web-core/log" "io/ioutil" + "os" "path/filepath" ) const ( keysDir = "keys" + + encKeysBytes = 32 ) var ( @@ -40,3 +45,39 @@ func initKeys(app *app) error { return nil } + +// generateKey generates a key at the given path used for the encryption of +// certain user data. Because user data becomes unrecoverable without these +// keys, this won't overwrite any existing key, and instead outputs a message. +func generateKey(path string) error { + // Check if key file exists + if _, err := os.Stat(path); !os.IsNotExist(err) { + log.Info("%s already exists. rm the file if you understand the consquences.", path) + return nil + } + + log.Info("Generating %s.", path) + b, err := generateBytes(encKeysBytes) + if err != nil { + log.Error("FAILED. %s. Run writefreely --gen-keys again.", err) + return err + } + err = ioutil.WriteFile(path, b, 0600) + if err != nil { + log.Error("FAILED writing file: %s", err) + return err + } + log.Info("Success.") + return nil +} + +// generateBytes returns securely generated random bytes. +func generateBytes(n int) ([]byte, error) { + b := make([]byte, n) + _, err := rand.Read(b) + if err != nil { + return nil, err + } + + return b, nil +} diff --git a/keys.sh b/keys.sh deleted file mode 100755 index d4c0c22..0000000 --- a/keys.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# -# keys.sh generates keys used for the encryption of certain user data. Because -# user data becomes unrecoverable without these keys, the script and won't -# overwrite any existing keys unless you explicitly delete them. -# - -# Generate cookie encryption and authentication keys -if [[ ! -e "$(pwd)/keys/cookies_enc.aes256" ]]; then - dd of=$(pwd)/keys/cookies_enc.aes256 if=/dev/urandom bs=32 count=1 -else - echo "cookies key already exists! rm keys/cookies_enc.aes256 if you understand the consquences." -fi -if [[ ! -e "$(pwd)/keys/cookies_auth.aes256" ]]; then - dd of=$(pwd)/keys/cookies_auth.aes256 if=/dev/urandom bs=32 count=1 -else - echo "cookies authentication key already exists! rm keys/cookies_auth.aes256 if you understand the consquences." -fi - -# Generate email encryption key -if [[ ! -e "$(pwd)/keys/email.aes256" ]]; then - dd of=$(pwd)/keys/email.aes256 if=/dev/urandom bs=32 count=1 -else - echo "email key already exists! rm keys/email.aes256 if you understand the consquences." -fi diff --git a/keys/README.md b/keys/README.md index 966b9a9..49c7417 100644 --- a/keys/README.md +++ b/keys/README.md @@ -1,4 +1,4 @@ Keys ==== -Contains keys for encrypting database and session data. Generate necessary keys by running (from the root of the project) `./keys.sh`. +Contains keys for encrypting database and session data. Generate necessary keys by running (from the root of the project) `writefreely --gen-keys`.