Files
monlet/agent/internal/agentkey/agentkey.go
2026-05-28 14:19:27 +04:00

76 lines
1.6 KiB
Go

package agentkey
import (
"crypto/rand"
"encoding/hex"
"fmt"
"os"
"path/filepath"
"strings"
)
const (
fileName = "agent.key"
keyBytes = 32
keyLen = keyBytes * 2
)
func LoadOrCreate(stateDir string) (string, error) {
if err := os.MkdirAll(stateDir, 0o700); err != nil {
return "", err
}
if err := os.Chmod(stateDir, 0o700); err != nil {
return "", err
}
path := filepath.Join(stateDir, fileName)
if info, err := os.Stat(path); err == nil {
if !info.Mode().IsRegular() {
return "", fmt.Errorf("agent key is not a regular file: %s", path)
}
if info.Mode().Perm() != 0o600 {
if err := os.Chmod(path, 0o600); err != nil {
return "", err
}
}
b, err := os.ReadFile(path)
if err != nil {
return "", err
}
return validate(strings.TrimSpace(string(b)), path)
} else if !os.IsNotExist(err) {
return "", err
}
key, err := generate()
if err != nil {
return "", err
}
tmp := fmt.Sprintf("%s.%d.tmp", path, os.Getpid())
defer os.Remove(tmp)
if err := os.WriteFile(tmp, []byte(key+"\n"), 0o600); err != nil {
return "", err
}
if err := os.Rename(tmp, path); err != nil {
return "", err
}
return key, nil
}
func validate(key string, path string) (string, error) {
if len(key) != keyLen {
return "", fmt.Errorf("invalid agent key in %s", path)
}
if _, err := hex.DecodeString(key); err != nil {
return "", fmt.Errorf("invalid agent key in %s", path)
}
return strings.ToLower(key), nil
}
func generate() (string, error) {
var b [keyBytes]byte
if _, err := rand.Read(b[:]); err != nil {
return "", err
}
return hex.EncodeToString(b[:]), nil
}