Spaces:
Runtime error
Runtime error
| package config | |
| import ( | |
| "crypto/rand" | |
| "crypto/rsa" | |
| "crypto/x509" | |
| "encoding/json" | |
| "encoding/pem" | |
| "fmt" | |
| "os" | |
| "strings" | |
| ) | |
| type Peer struct { | |
| URL string | |
| PublicKey *rsa.PublicKey | |
| } | |
| type Config struct { | |
| DBPath string `json:"db_path"` | |
| TargetURL string `json:"target_url"` | |
| Port string `json:"port"` | |
| MaxParallelRequests int `json:"max_parallel_requests"` | |
| TrustedPeers []Peer `json:"trusted_peers"` | |
| TrustedPeersPath string `json:"trusted_peers_path"` | |
| } | |
| type Secrets struct { | |
| PrivateKeyPath string `json:"jwt_private_key_path"` | |
| PublicKeyPath string `json:"jwt_public_key_path"` | |
| } | |
| type KeyPair struct { | |
| PrivateKey *rsa.PrivateKey | |
| PublicKey *rsa.PublicKey | |
| } | |
| func LoadConfig(path string) (*Config, error) { | |
| file, err := os.ReadFile(path) | |
| if err != nil { | |
| return nil, err | |
| } | |
| var cfg Config | |
| err = json.Unmarshal(file, &cfg) | |
| return &cfg, err | |
| } | |
| func LoadSecrets(path string) (*Secrets, error) { | |
| file, err := os.ReadFile(path) | |
| if err != nil { | |
| return nil, err | |
| } | |
| var secrets Secrets | |
| err = json.Unmarshal(file, &secrets) | |
| return &secrets, err | |
| } | |
| func generateRSAKeys() (*rsa.PrivateKey, error) { | |
| return rsa.GenerateKey(rand.Reader, 2048) | |
| } | |
| func saveKeyToFile(key interface{}, path string) error { | |
| file, err := os.Create(path) | |
| if err != nil { | |
| return err | |
| } | |
| defer file.Close() | |
| var pemBlock *pem.Block | |
| switch k := key.(type) { | |
| case *rsa.PrivateKey: | |
| bytes, err := x509.MarshalPKCS8PrivateKey(k) | |
| if err != nil { | |
| return err | |
| } | |
| pemBlock = &pem.Block{ | |
| Type: "PRIVATE KEY", | |
| Bytes: bytes, | |
| } | |
| case *rsa.PublicKey: | |
| bytes, err := x509.MarshalPKIXPublicKey(k) | |
| if err != nil { | |
| return err | |
| } | |
| pemBlock = &pem.Block{ | |
| Type: "PUBLIC KEY", | |
| Bytes: bytes, | |
| } | |
| default: | |
| return fmt.Errorf("unsupported key type") | |
| } | |
| return pem.Encode(file, pemBlock) | |
| } | |
| func loadKeyFromFile(path string, private bool) (interface{}, error) { | |
| data, err := os.ReadFile(path) | |
| if err != nil { | |
| return nil, err | |
| } | |
| block, _ := pem.Decode(data) | |
| if block == nil { | |
| return nil, fmt.Errorf("failed to parse PEM block") | |
| } | |
| if private { | |
| key, err := x509.ParsePKCS8PrivateKey(block.Bytes) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return key.(*rsa.PrivateKey), nil | |
| } | |
| return x509.ParsePKIXPublicKey(block.Bytes) | |
| } | |
| func ensureKeysExist(secrets *Secrets) (*KeyPair, error) { | |
| if _, err := os.Stat(secrets.PrivateKeyPath); os.IsNotExist(err) { | |
| privateKey, err := generateRSAKeys() | |
| if err != nil { | |
| return nil, err | |
| } | |
| if err := saveKeyToFile(privateKey, secrets.PrivateKeyPath); err != nil { | |
| return nil, err | |
| } | |
| if err := saveKeyToFile(&privateKey.PublicKey, secrets.PublicKeyPath); err != nil { | |
| return nil, err | |
| } | |
| } | |
| privateKey, err := loadKeyFromFile(secrets.PrivateKeyPath, true) | |
| if err != nil { | |
| return nil, err | |
| } | |
| publicKey, err := loadKeyFromFile(secrets.PublicKeyPath, false) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return &KeyPair{ | |
| PrivateKey: privateKey.(*rsa.PrivateKey), | |
| PublicKey: publicKey.(*rsa.PublicKey), | |
| }, nil | |
| } | |
| func LoadTrustedPeers(path string) ([]Peer, error) { | |
| data, err := os.ReadFile(path) | |
| if err != nil { | |
| return nil, err | |
| } | |
| var peers []Peer | |
| lines := strings.Split(string(data), "\n") | |
| for _, line := range lines { | |
| line = strings.TrimSpace(line) | |
| if line == "" || strings.HasPrefix(line, "#") { | |
| continue | |
| } | |
| parts := strings.SplitN(line, "|", 2) | |
| if len(parts) != 2 { | |
| continue | |
| } | |
| block, _ := pem.Decode([]byte(parts[1])) | |
| if block == nil { | |
| continue | |
| } | |
| pubKey, err := x509.ParsePKIXPublicKey(block.Bytes) | |
| if err != nil { | |
| continue | |
| } | |
| peers = append(peers, Peer{ | |
| URL: parts[0], | |
| PublicKey: pubKey.(*rsa.PublicKey), | |
| }) | |
| } | |
| return peers, nil | |
| } | |
| func Load() (*Config, *Secrets, *KeyPair, error) { | |
| cfg, err := LoadConfig("/app/files/config.json") | |
| if err != nil { | |
| return nil, nil, nil, err | |
| } | |
| secrets, err := LoadSecrets("/app/files/secrets.json") | |
| if err != nil { | |
| return nil, nil, nil, err | |
| } | |
| keyPair, err := ensureKeysExist(secrets) | |
| if err != nil { | |
| return nil, nil, nil, err | |
| } | |
| if cfg.TrustedPeersPath != "" { | |
| peers, err := LoadTrustedPeers(cfg.TrustedPeersPath) | |
| if err != nil { | |
| return nil, nil, nil, err | |
| } | |
| cfg.TrustedPeers = peers | |
| } | |
| return cfg, secrets, keyPair, nil | |
| } | |