142 lines
2.8 KiB
Go
142 lines
2.8 KiB
Go
package tools
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
// PathExists returns whether the given file or directory exists or not
|
|
func PathExists(path string) (bool, error) {
|
|
_, err := os.Stat(path)
|
|
if err == nil {
|
|
return true, nil
|
|
}
|
|
if os.IsNotExist(err) {
|
|
return false, nil
|
|
}
|
|
return false, err
|
|
}
|
|
|
|
var jsonConfigTemplate = `{
|
|
"client": {
|
|
"token": {
|
|
"hmac_secret_key": "{{.TokenSecret}}"
|
|
},
|
|
"allowed_origins": []
|
|
},
|
|
"admin": {
|
|
"enabled": false,
|
|
"password": "{{.AdminPassword}}",
|
|
"secret": "{{.AdminSecret}}"
|
|
},
|
|
"http_api": {
|
|
"key": "{{.APIKey}}"
|
|
}
|
|
}
|
|
`
|
|
|
|
var tomlConfigTemplate = `[client]
|
|
allowed_origins = []
|
|
|
|
[client.token]
|
|
hmac_secret_key = "{{.TokenSecret}}"
|
|
|
|
[admin]
|
|
enabled = false
|
|
password = "{{.AdminPassword}}"
|
|
secret = "{{.AdminSecret}}"
|
|
|
|
[http_api]
|
|
key = "{{.APIKey}}"
|
|
`
|
|
|
|
var yamlConfigTemplate = `client:
|
|
token:
|
|
hmac_secret_key: "{{.TokenSecret}}"
|
|
allowed_origins: []
|
|
|
|
admin:
|
|
enabled: false
|
|
password: "{{.AdminPassword}}"
|
|
secret: "{{.AdminSecret}}"
|
|
|
|
http_api:
|
|
key: "{{.APIKey}}"
|
|
`
|
|
|
|
// GenerateConfig generates configuration file at provided path.
|
|
func GenerateConfig(f string) error {
|
|
exists, err := PathExists(f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if exists {
|
|
return errors.New("output config file already exists: " + f)
|
|
}
|
|
ext := filepath.Ext(f)
|
|
|
|
if len(ext) > 1 {
|
|
ext = ext[1:]
|
|
}
|
|
|
|
supportedExtensions := []string{"json", "toml", "yaml", "yml"}
|
|
|
|
var t *template.Template
|
|
|
|
switch ext {
|
|
case "json":
|
|
t, err = template.New("config").Parse(jsonConfigTemplate)
|
|
case "toml":
|
|
t, err = template.New("config").Parse(tomlConfigTemplate)
|
|
case "yaml", "yml":
|
|
t, err = template.New("config").Parse(yamlConfigTemplate)
|
|
default:
|
|
return errors.New("output config file must have one of supported extensions: " + strings.Join(supportedExtensions, ", "))
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var output bytes.Buffer
|
|
_ = t.Execute(&output, struct {
|
|
TokenSecret string
|
|
AdminPassword string
|
|
AdminSecret string
|
|
APIKey string
|
|
}{
|
|
mustGenerateSecretKey(64),
|
|
mustGenerateSecretKey(16),
|
|
mustGenerateSecretKey(64),
|
|
mustGenerateSecretKey(64),
|
|
})
|
|
|
|
return os.WriteFile(f, output.Bytes(), 0600)
|
|
}
|
|
|
|
func OptionalStringChoice(value string, choices []string) (string, error) {
|
|
if value == "" {
|
|
// Empty value is valid for optional configuration key.
|
|
return value, nil
|
|
}
|
|
if !slices.Contains(choices, value) {
|
|
return "", fmt.Errorf("invalid value: %s, possible choices are: %s", value, strings.Join(choices, ", "))
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
func mustGenerateSecretKey(byteLen int) string {
|
|
key := make([]byte, byteLen)
|
|
if _, err := rand.Read(key); err != nil {
|
|
panic(err)
|
|
}
|
|
return base64.RawURLEncoding.EncodeToString(key)
|
|
}
|