Harden config perms and key derivation
CI / check-and-test (pull_request) Successful in 11s

Write generated configs 0600, treat new keys as raw AES-256, keep
PBKDF2 for unprefixed material, and cache derivation at startup.
This commit is contained in:
s1d3sw1ped_bot
2026-09-01 04:22:57 +00:00
parent 45778ac528
commit bc486eb49d
8 changed files with 293 additions and 52 deletions
+19 -12
View File
@@ -1,8 +1,6 @@
package config
import (
"crypto/rand"
"encoding/hex"
"fmt"
"net"
"os"
@@ -609,24 +607,33 @@ func GenerateExampleConfig(filename string) error {
return fmt.Errorf("failed to marshal config: %v", err)
}
err = os.WriteFile(filename, data, 0644)
err = os.WriteFile(filename, data, 0o600)
if err != nil {
return fmt.Errorf("failed to write config file: %v", err)
}
if err := os.Chmod(filename, 0o600); err != nil {
return fmt.Errorf("failed to set config file permissions: %v", err)
}
fmt.Printf("Generated example configuration: %s\n", filename)
fmt.Printf("Edit the configuration file and run: ./teleport -config %s\n", filename)
return nil
}
// generateStrongEncryptionKey generates a cryptographically secure encryption key
// generateStrongEncryptionKey generates a raw 256-bit key (raw: + 64 hex chars).
func generateStrongEncryptionKey() (string, error) {
// Generate 32 random bytes (256 bits) for a strong encryption key
bytes := make([]byte, 32)
if _, err := rand.Read(bytes); err != nil {
return "", fmt.Errorf("failed to generate random key: %v", err)
}
// Convert to hexadecimal string for easy copying
return hex.EncodeToString(bytes), nil
return encryption.GenerateRawKey()
}
// ApplyTCPKeepAlive enables TCP keep-alive when enabled is true.
func ApplyTCPKeepAlive(conn net.Conn, enabled bool) {
if conn == nil || !enabled {
return
}
tcp, ok := conn.(*net.TCPConn)
if !ok {
return
}
_ = tcp.SetKeepAlive(true)
_ = tcp.SetKeepAlivePeriod(30 * time.Second)
}
+60
View File
@@ -7,6 +7,8 @@ import (
"strings"
"testing"
"time"
"teleport/pkg/encryption"
)
func TestLoadConfig(t *testing.T) {
@@ -585,3 +587,61 @@ func TestGenerateExampleConfigUsesLoopback(t *testing.T) {
t.Fatalf("generated client local listen %q", got)
}
}
func TestGenerateExampleConfigMode0600(t *testing.T) {
tempDir := t.TempDir()
configFile := filepath.Join(tempDir, "server.yaml")
if err := GenerateExampleConfig(configFile); err != nil {
t.Fatal(err)
}
st, err := os.Stat(configFile)
if err != nil {
t.Fatal(err)
}
if st.Mode().Perm() != 0o600 {
t.Fatalf("generated config mode %04o want 0600", st.Mode().Perm())
}
cfg, err := LoadConfig(configFile)
if err != nil {
t.Fatalf("reload generated config: %v", err)
}
if !encryption.IsRawKey(cfg.EncryptionKey) {
t.Fatalf("generated encryption_key is not raw: %q", cfg.EncryptionKey[:min(8, len(cfg.EncryptionKey))])
}
key, err := encryption.ResolveKey(cfg.EncryptionKey)
if err != nil {
t.Fatal(err)
}
if len(key) != 32 {
t.Fatalf("resolved key len %d", len(key))
}
}
func TestApplyTCPKeepAlive(t *testing.T) {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
defer ln.Close()
errCh := make(chan error, 1)
go func() {
c, err := ln.Accept()
if err != nil {
errCh <- err
return
}
defer c.Close()
ApplyTCPKeepAlive(c, true)
errCh <- nil
}()
conn, err := net.Dial("tcp", ln.Addr().String())
if err != nil {
t.Fatal(err)
}
defer conn.Close()
ApplyTCPKeepAlive(conn, true)
ApplyTCPKeepAlive(conn, false)
if err := <-errCh; err != nil {
t.Fatal(err)
}
}