Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions docs/security-logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- SPDX-FileCopyrightText: Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC -->
<!-- SPDX-License-Identifier: MIT -->

# WireGuard startup diagnostics

Successful WireGuard startup logs the interface name, public key, listen port and
server address. It does not log the server private key at INFO or DEBUG level.
Key generation, temporary-file cleanup and interface configuration are unchanged.

This change requires no configuration or client migration. It does not introduce
JWT requirements or change API access, bootstrap identity or peer ownership.
Previously retained logs may already contain the private key; removing the log
field does not rotate that key or remove old log copies.
59 changes: 59 additions & 0 deletions pkg/wgtunnel/startup_logging_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-FileCopyrightText: Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC
// SPDX-License-Identifier: MIT

package wgtunnel

import (
"bytes"
"os"
"path/filepath"
"strings"
"testing"

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)

func TestStartServerDoesNotLogPrivateKey(t *testing.T) {
const privateKey = "fixture-private-key-must-not-be-logged"
const publicKey = "fixture-server-public-key"
commands := t.TempDir()
for name, script := range map[string]string{
"ip": "#!/bin/sh\nexit 0\n",
"wg": "#!/bin/sh\nif [ \"$1\" = show ]; then printf '%s\\n' '" + publicKey + "'; fi\n",
} {
if err := os.WriteFile(filepath.Join(commands, name), []byte(script), 0o700); err != nil {
t.Fatal(err)
}
}
// Only fake commands can run; this test never creates a host interface.
t.Setenv("PATH", commands)
keyFiles := t.TempDir()
t.Setenv("TMPDIR", keyFiles)
originalLogger := log.Logger
t.Cleanup(func() { log.Logger = originalLogger })
for _, level := range []zerolog.Level{zerolog.InfoLevel, zerolog.DebugLevel} {
t.Run(level.String(), func(t *testing.T) {
var output bytes.Buffer
log.Logger = zerolog.New(&output).Level(level)
manager := newTestInterfaceManager(t)
manager.privateKey = privateKey
if err := manager.StartServer(); err != nil {
t.Fatal(err)
}
if manager.publicKey != publicKey || manager.privateKey != privateKey {
t.Fatal("startup changed key configuration")
}
if strings.Contains(output.String(), privateKey) || strings.Contains(output.String(), "Private Key") {
t.Error("WireGuard startup logged its private key")
}
if !strings.Contains(output.String(), "Wireguard Server Configured") || !strings.Contains(output.String(), publicKey) {
t.Error("missing useful public startup diagnostics")
}
files, err := os.ReadDir(keyFiles)
if err != nil || len(files) != 0 {
t.Fatal("startup did not clean up the temporary private-key file")
}
})
}
}
1 change: 0 additions & 1 deletion pkg/wgtunnel/tunnels.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ func (m *InterfaceManager) StartServer() error {

log.Info().
Str("Interface Name", m.interfaceName).
Str("Private Key", m.privateKey).
Str("Public Key", m.publicKey).
Int("Listen Port", m.listenPort).
Str("IP Address", m.ipAddress.String()).
Expand Down
Loading