Merge pull request #1 from AYM1607/better-keys-envs
Better server config
This commit is contained in:
commit
cf02b18ede
7 changed files with 123 additions and 87 deletions
|
|
@ -4,24 +4,12 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/AYM1607/ccclip/internal/config"
|
|
||||||
"github.com/AYM1607/ccclip/internal/server"
|
"github.com/AYM1607/ccclip/internal/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
privateKeyPath := os.Getenv("CCCLIP_PRIVATE_KEY")
|
|
||||||
publicKeyPath := os.Getenv("CCCLIP_PUBLIC_KEY")
|
|
||||||
databaseLocation := os.Getenv("CCCLIP_DATABASE_LOCATION")
|
|
||||||
port := os.Getenv("CCCLIP_PORT")
|
port := os.Getenv("CCCLIP_PORT")
|
||||||
|
|
||||||
if publicKeyPath == "" || privateKeyPath == "" {
|
|
||||||
log.Fatalf("database location and public and privae keys must be provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Default.PrivateKeyPath = privateKeyPath
|
|
||||||
config.Default.PublicKeyPath = publicKeyPath
|
|
||||||
config.Default.DatabaseLocation = databaseLocation
|
|
||||||
|
|
||||||
if port == "" {
|
if port == "" {
|
||||||
port = "8080"
|
port = "8080"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
fly.toml
1
fly.toml
|
|
@ -10,7 +10,6 @@ primary_region = "sea"
|
||||||
dockerfile = "./cmd/server/Dockerfile"
|
dockerfile = "./cmd/server/Dockerfile"
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
CCCLIP_LOAD_RAW_KEYS = "true"
|
|
||||||
CCCLIP_PORT = "3000"
|
CCCLIP_PORT = "3000"
|
||||||
CCCLIP_DATABASE_LOCATION = "/litefs/ccclip.db"
|
CCCLIP_DATABASE_LOCATION = "/litefs/ccclip.db"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,20 +55,20 @@ func Write(c ConfigFile) error {
|
||||||
|
|
||||||
func LoadPrivateKey() (*ecdh.PrivateKey, error) {
|
func LoadPrivateKey() (*ecdh.PrivateKey, error) {
|
||||||
fp := path.Join(Path, PrivateKeyFileName)
|
fp := path.Join(Path, PrivateKeyFileName)
|
||||||
return crypto.LoadPrivateKey(fp)
|
return crypto.LoadPrivateKeyFromFile(fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadPublicKey() (*ecdh.PublicKey, error) {
|
func LoadPublicKey() (*ecdh.PublicKey, error) {
|
||||||
fp := path.Join(Path, PublicKeyFileName)
|
fp := path.Join(Path, PublicKeyFileName)
|
||||||
return crypto.LoadPublicKey(fp)
|
return crypto.LoadPublicKeyFromFile(fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SavePrivateKey(k *ecdh.PrivateKey) error {
|
func SavePrivateKey(k *ecdh.PrivateKey) error {
|
||||||
fp := path.Join(Path, PrivateKeyFileName)
|
fp := path.Join(Path, PrivateKeyFileName)
|
||||||
return crypto.SavePrivateKey(fp, k)
|
return crypto.SavePrivateKeyToFile(fp, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SavePublicKey(k *ecdh.PublicKey) error {
|
func SavePublicKey(k *ecdh.PublicKey) error {
|
||||||
fp := path.Join(Path, PublicKeyFileName)
|
fp := path.Join(Path, PublicKeyFileName)
|
||||||
return crypto.SavePublicKey(fp, k)
|
return crypto.SavePublicKeyToFile(fp, k)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
internal/server/keys.go
Normal file
40
internal/server/keys.go
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdh"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/AYM1607/ccclip/pkg/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
privateKeyEnv = "CCCLIP_PRIVATE_KEY"
|
||||||
|
publicKeyEnv = "CCCLIP_PUBLIC_KEY"
|
||||||
|
privateKeyPathEnv = "CCCLIP_PRIVATE_KEY_PATH"
|
||||||
|
publicKeyPathEnv = "CCCLIP_PUBLIC_KEY_PATH"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loadKeys() (*ecdh.PrivateKey, *ecdh.PublicKey, error) {
|
||||||
|
// Prioritize explicit keys over files.
|
||||||
|
var pvk *ecdh.PrivateKey
|
||||||
|
var pbk *ecdh.PublicKey
|
||||||
|
|
||||||
|
if b64PrivateKey := os.Getenv(privateKeyEnv); b64PrivateKey != "" {
|
||||||
|
pvk = crypto.PrivateKeyFromB64([]byte(b64PrivateKey))
|
||||||
|
} else if privateKeyPath := os.Getenv(privateKeyPathEnv); privateKeyPath != "" {
|
||||||
|
pvk = crypto.LoadPrivateKeyFromFile(privateKeyPath)
|
||||||
|
} else {
|
||||||
|
return nil, nil, errors.New("no private key was found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if b64PublicKey := os.Getenv(publicKeyEnv); b64PublicKey != "" {
|
||||||
|
pbk = crypto.PublicKeyFromB64([]byte(b64PublicKey))
|
||||||
|
} else if publicKeyPath := os.Getenv(publicKeyPathEnv); publicKeyPath != "" {
|
||||||
|
pbk = crypto.LoadPublicKeyFromFile(publicKeyPath)
|
||||||
|
} else {
|
||||||
|
return nil, nil, errors.New("to public key was found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return pvk, pbk, nil
|
||||||
|
}
|
||||||
|
|
@ -3,16 +3,16 @@ package server
|
||||||
import (
|
import (
|
||||||
"crypto/ecdh"
|
"crypto/ecdh"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
||||||
"github.com/AYM1607/ccclip/internal/config"
|
|
||||||
"github.com/AYM1607/ccclip/internal/db"
|
"github.com/AYM1607/ccclip/internal/db"
|
||||||
"github.com/AYM1607/ccclip/pkg/api"
|
"github.com/AYM1607/ccclip/pkg/api"
|
||||||
"github.com/AYM1607/ccclip/pkg/crypto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(addr string) *http.Server {
|
func New(addr string) *http.Server {
|
||||||
|
|
@ -24,7 +24,10 @@ func New(addr string) *http.Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const minPasswordWork = 12
|
const (
|
||||||
|
minPasswordWork = 12
|
||||||
|
dbLocationEnv = "CCCLIP_DATABASE_LOCATION"
|
||||||
|
)
|
||||||
|
|
||||||
type controller struct {
|
type controller struct {
|
||||||
store db.DB
|
store db.DB
|
||||||
|
|
@ -37,20 +40,16 @@ type controller struct {
|
||||||
func newHttpHandler() http.Handler {
|
func newHttpHandler() http.Handler {
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
|
|
||||||
pbk, err := crypto.LoadPublicKey(config.Default.PublicKeyPath)
|
pvk, pbk, err := loadKeys()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("could not load server's public key")
|
panic(fmt.Errorf("could not load keys for the server: %w", err))
|
||||||
}
|
|
||||||
pvk, err := crypto.LoadPrivateKey(config.Default.PrivateKeyPath)
|
|
||||||
if err != nil {
|
|
||||||
panic("could not load server's private key")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var store db.DB
|
var store db.DB
|
||||||
if config.Default.DatabaseLocation == "" {
|
if dbLocation := os.Getenv(dbLocationEnv); dbLocation != "" {
|
||||||
store = db.NewLocalDB()
|
store = db.NewSQLiteDB(dbLocation)
|
||||||
} else {
|
} else {
|
||||||
store = db.NewSQLiteDB(config.Default.DatabaseLocation)
|
store = db.NewLocalDB()
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &controller{
|
c := &controller{
|
||||||
|
|
|
||||||
50
pkg/crypto/key_files.go
Normal file
50
pkg/crypto/key_files.go
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdh"
|
||||||
|
"encoding/base64"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadPrivateKeyFromFile(fp string) *ecdh.PrivateKey {
|
||||||
|
kb, err := loadKeyFile(fp)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return PrivateKeyFromBytes(kb)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadPublicKeyFromFile(fp string) *ecdh.PublicKey {
|
||||||
|
kb, err := loadKeyFile(fp)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return PublicKeyFromBytes(kb)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SavePrivateKeyToFile(fp string, k *ecdh.PrivateKey) error {
|
||||||
|
return saveKeyFile(fp, k.Bytes(), privateKeyFileMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SavePublicKeyToFile(fp string, k *ecdh.PublicKey) error {
|
||||||
|
return saveKeyFile(fp, k.Bytes(), publicKeyFileMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadKeyFile(fp string) ([]byte, error) {
|
||||||
|
b64Key, err := os.ReadFile(fp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
keyBytes := make([]byte, KeySize)
|
||||||
|
base64.StdEncoding.Decode(keyBytes, b64Key)
|
||||||
|
return keyBytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func saveKeyFile(fp string, key []byte, fm os.FileMode) error {
|
||||||
|
b64Key := make([]byte, base64.StdEncoding.EncodedLen(len(key)))
|
||||||
|
base64.StdEncoding.Encode(b64Key, key)
|
||||||
|
|
||||||
|
return os.WriteFile(fp, b64Key, fm)
|
||||||
|
}
|
||||||
|
|
@ -64,6 +64,24 @@ func NewSharedKey(local *ecdh.PrivateKey, remote *ecdh.PublicKey, direction Dire
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PrivateKeyFromB64(encodedKey []byte) *ecdh.PrivateKey {
|
||||||
|
keyBytes := make([]byte, base64.StdEncoding.DecodedLen(len(encodedKey)))
|
||||||
|
_, err := base64.StdEncoding.Decode(keyBytes, encodedKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not decode base64 private key: %w", err))
|
||||||
|
}
|
||||||
|
return PrivateKeyFromBytes(keyBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PublicKeyFromB64(encodedKey []byte) *ecdh.PublicKey {
|
||||||
|
keyBytes := make([]byte, base64.StdEncoding.DecodedLen(len(encodedKey)))
|
||||||
|
_, err := base64.StdEncoding.Decode(keyBytes, encodedKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("could not decode base64 public key: %w", err))
|
||||||
|
}
|
||||||
|
return PublicKeyFromBytes(keyBytes)
|
||||||
|
}
|
||||||
|
|
||||||
func PrivateKeyFromBytes(keyBytes []byte) *ecdh.PrivateKey {
|
func PrivateKeyFromBytes(keyBytes []byte) *ecdh.PrivateKey {
|
||||||
key, err := ecdh.X25519().NewPrivateKey(keyBytes)
|
key, err := ecdh.X25519().NewPrivateKey(keyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -79,61 +97,3 @@ func PublicKeyFromBytes(keyBytes []byte) *ecdh.PublicKey {
|
||||||
}
|
}
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadPrivateKey(fp string) (*ecdh.PrivateKey, error) {
|
|
||||||
var kb []byte
|
|
||||||
var err error
|
|
||||||
if os.Getenv("CCCLIP_LOAD_RAW_KEYS") == "" {
|
|
||||||
kb, err = loadKey(fp)
|
|
||||||
} else {
|
|
||||||
kb = make([]byte, KeySize)
|
|
||||||
base64.StdEncoding.Decode(kb, []byte(fp))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return PrivateKeyFromBytes(kb), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadPublicKey(fp string) (*ecdh.PublicKey, error) {
|
|
||||||
var kb []byte
|
|
||||||
var err error
|
|
||||||
if os.Getenv("CCCLIP_LOAD_RAW_KEYS") == "" {
|
|
||||||
kb, err = loadKey(fp)
|
|
||||||
} else {
|
|
||||||
kb = make([]byte, KeySize)
|
|
||||||
base64.StdEncoding.Decode(kb, []byte(fp))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return PublicKeyFromBytes(kb), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func SavePrivateKey(fp string, k *ecdh.PrivateKey) error {
|
|
||||||
return saveKey(fp, k.Bytes(), privateKeyFileMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SavePublicKey(fp string, k *ecdh.PublicKey) error {
|
|
||||||
return saveKey(fp, k.Bytes(), publicKeyFileMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadKey(fp string) ([]byte, error) {
|
|
||||||
b64Key, err := os.ReadFile(fp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
keyBytes := make([]byte, KeySize)
|
|
||||||
base64.StdEncoding.Decode(keyBytes, b64Key)
|
|
||||||
return keyBytes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveKey(fp string, key []byte, fm os.FileMode) error {
|
|
||||||
b64Key := make([]byte, base64.StdEncoding.EncodedLen(len(key)))
|
|
||||||
base64.StdEncoding.Encode(b64Key, key)
|
|
||||||
|
|
||||||
return os.WriteFile(fp, b64Key, fm)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue