snapshot of https://github.com/nats-io/nats-server.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
NATS Server Tests / Lint (push) Failing after 3s
NATS Server Tests / Build (Latest Go) (push) Has been skipped
NATS Server Tests / Build (Minimum Go) (push) Has been skipped
NATS Server Tests / Build (Minimum Go, windows-2022) (push) Has been skipped
NATS Server Tests / Build (Minimum Go, windows-2025) (push) Has been skipped
NATS Server Tests / Test Stores (push) Has been skipped
NATS Server Tests / Test JetStream (push) Has been skipped
NATS Server Tests / Test Raft (push) Has been skipped
NATS Server Tests / Test JetStream Consumers (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 1 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 2 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 3 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 4 (push) Has been skipped
NATS Server Tests / Test JetStream Supercluster (push) Has been skipped
NATS Server Tests / Test No-Race 1 (push) Has been skipped
NATS Server Tests / Test No-Race 2 (push) Has been skipped
NATS Server Tests / Test MQTT (push) Has been skipped
NATS Server Tests / Test Message Tracing (push) Has been skipped
NATS Server Tests / Test JWT (push) Has been skipped
NATS Server Tests / Test Remaining Server Tests (push) Has been skipped
NATS Server Tests / Test Other Packages (push) Has been skipped
Vulnerability Scan / govulncheck (push) Failing after 12m2s
Some checks failed
NATS Server Tests / Lint (push) Failing after 3s
NATS Server Tests / Build (Latest Go) (push) Has been skipped
NATS Server Tests / Build (Minimum Go) (push) Has been skipped
NATS Server Tests / Build (Minimum Go, windows-2022) (push) Has been skipped
NATS Server Tests / Build (Minimum Go, windows-2025) (push) Has been skipped
NATS Server Tests / Test Stores (push) Has been skipped
NATS Server Tests / Test JetStream (push) Has been skipped
NATS Server Tests / Test Raft (push) Has been skipped
NATS Server Tests / Test JetStream Consumers (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 1 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 2 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 3 (push) Has been skipped
NATS Server Tests / Test JetStream Cluster 4 (push) Has been skipped
NATS Server Tests / Test JetStream Supercluster (push) Has been skipped
NATS Server Tests / Test No-Race 1 (push) Has been skipped
NATS Server Tests / Test No-Race 2 (push) Has been skipped
NATS Server Tests / Test MQTT (push) Has been skipped
NATS Server Tests / Test Message Tracing (push) Has been skipped
NATS Server Tests / Test JWT (push) Has been skipped
NATS Server Tests / Test Remaining Server Tests (push) Has been skipped
NATS Server Tests / Test Other Packages (push) Has been skipped
Vulnerability Scan / govulncheck (push) Failing after 12m2s
This commit is contained in:
248
server/jetstream_tpm_test.go
Normal file
248
server/jetstream_tpm_test.go
Normal file
@@ -0,0 +1,248 @@
|
||||
// Copyright 2024 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build windows
|
||||
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
)
|
||||
|
||||
// The tests in this file are not complete, but are a start to test the TPM
|
||||
// with default settings. For a complete test we would need to use a TPM
|
||||
// configured with an owner password and a SRK password. This is not
|
||||
// typically the default or setup in CI/CD environments.
|
||||
|
||||
var jsTPMConfigPassword = `
|
||||
listen: 127.0.0.1:-1
|
||||
jetstream: {
|
||||
store_dir: %q
|
||||
tpm {
|
||||
keys_file: %q
|
||||
encryption_password: "s3cr3t!"
|
||||
}
|
||||
}`
|
||||
|
||||
var jsTPMConfigBadPassword = `
|
||||
listen: 127.0.0.1:-1
|
||||
jetstream: {
|
||||
store_dir: %q
|
||||
tpm {
|
||||
keys_file: %q
|
||||
encryption_password: "garbage"
|
||||
}
|
||||
}`
|
||||
|
||||
var jsTPMConfigPasswordPcr = `
|
||||
listen: 127.0.0.1:-1
|
||||
jetstream: {
|
||||
store_dir: %q
|
||||
tpm {
|
||||
keys_file: %q
|
||||
encryption_password: "s3cr3t!"
|
||||
pcr: %d
|
||||
}
|
||||
}`
|
||||
|
||||
var jsTPMConfigAllFields = `
|
||||
listen: 127.0.0.1:-1
|
||||
jetstream: {
|
||||
store_dir: %q
|
||||
tpm {
|
||||
keys_file: %q
|
||||
encryption_password: "s3cr3t!"
|
||||
pcr: %d
|
||||
srk_password: %q
|
||||
cipher: "aes"
|
||||
}
|
||||
}`
|
||||
|
||||
var jsTPMConfigInvalidBothOptionsSet = `
|
||||
listen: 127.0.0.1:-1
|
||||
jetstream: {
|
||||
store_dir: %q
|
||||
encryption_key: "foo"
|
||||
tpm {
|
||||
keys_file: "bar.json"
|
||||
encryption_password: "s3cr3t!"
|
||||
}
|
||||
}`
|
||||
|
||||
func getTPMFileName(t *testing.T) string {
|
||||
return t.TempDir() + "/" + t.Name() + "/jskeys.json"
|
||||
}
|
||||
|
||||
func checkSendMessage(t *testing.T, s *Server) {
|
||||
nc, js := jsClientConnect(t, s)
|
||||
defer nc.Close()
|
||||
|
||||
_, err := js.AddStream(&nats.StreamConfig{
|
||||
Name: "tpm_test",
|
||||
Subjects: []string{"tpm_test"},
|
||||
})
|
||||
require_NoError(t, err)
|
||||
|
||||
_, err = js.Publish("tpm_test", []byte("hello"))
|
||||
require_NoError(t, err)
|
||||
}
|
||||
|
||||
func checkReceiveMessage(t *testing.T, s *Server) {
|
||||
// reconnect and get the message
|
||||
nc, js := jsClientConnect(t, s)
|
||||
defer nc.Close()
|
||||
|
||||
// get the message
|
||||
sub, err := js.PullSubscribe("tpm_test", "cls")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
m := fetchMsgs(t, sub, 1, 5*time.Second)
|
||||
if m == nil {
|
||||
t.Fatalf("Did not receive the message")
|
||||
}
|
||||
if len(m) != 1 {
|
||||
t.Fatalf("Expected 1 message, got %d", len(m))
|
||||
}
|
||||
}
|
||||
|
||||
func TestJetStreamTPMBasic(t *testing.T) {
|
||||
fileName := getTPMFileName(t)
|
||||
cf := createConfFile(t, []byte(fmt.Sprintf(jsTPMConfigPassword, t.TempDir(), fileName)))
|
||||
|
||||
s, _ := RunServerWithConfig(cf)
|
||||
defer s.Shutdown()
|
||||
|
||||
// Note, actual encryption is tested elsewhere. This just tests that the key is generated.
|
||||
key := s.opts.JetStreamKey
|
||||
if !strings.HasPrefix(key, "SU") {
|
||||
t.Fatalf("expected a TPM key to be generated. Key = %q", key)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(fileName); err != nil {
|
||||
t.Fatalf("keys file was not created")
|
||||
}
|
||||
|
||||
checkSendMessage(t, s)
|
||||
|
||||
// restart the server.
|
||||
s.Shutdown()
|
||||
s, _ = RunServerWithConfig(cf)
|
||||
if s.Running() == false {
|
||||
t.Fatalf("Server should be running")
|
||||
}
|
||||
defer s.Shutdown()
|
||||
|
||||
// double check we're encrypted with the same key.
|
||||
if s.opts.JetStreamKey != key {
|
||||
t.Fatalf("expected same key")
|
||||
}
|
||||
checkReceiveMessage(t, s)
|
||||
}
|
||||
|
||||
// Warning: Running this test too frequently will considerably slow down
|
||||
// these tests and eventually lock out the TPM.
|
||||
//
|
||||
// Depending on the environment this varies from 10 failures per day with
|
||||
// a 24 hour lockout (Dell) to 32 failures per day with a 10
|
||||
// minute healing time (decrementing one failure every 10 minutes).
|
||||
func TestJetStreamTPMKeyBadPassword(t *testing.T) {
|
||||
fileName := getTPMFileName(t)
|
||||
cf := createConfFile(t, []byte(fmt.Sprintf(jsTPMConfigPassword,
|
||||
t.TempDir(), fileName)))
|
||||
|
||||
s, _ := RunServerWithConfig(cf)
|
||||
defer s.Shutdown()
|
||||
|
||||
checkSendMessage(t, s)
|
||||
s.Shutdown()
|
||||
|
||||
// restart the server.
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
t.Fatalf("Expected server panic, unexpected start.")
|
||||
}
|
||||
}()
|
||||
cf2 := createConfFile(t, []byte(fmt.Sprintf(jsTPMConfigBadPassword,
|
||||
t.TempDir(), fileName)))
|
||||
s, _ = RunServerWithConfig(cf2)
|
||||
time.Sleep(3 * time.Second)
|
||||
if s.Running() {
|
||||
s.Shutdown()
|
||||
t.Fatalf("Server should NOT be running")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJetStreamTPMKeyWithPCR(t *testing.T) {
|
||||
cf := createConfFile(t, []byte(fmt.Sprintf(jsTPMConfigPasswordPcr,
|
||||
t.TempDir(), getTPMFileName(t), 18)))
|
||||
|
||||
s, _ := RunServerWithConfig(cf)
|
||||
defer s.Shutdown()
|
||||
|
||||
checkSendMessage(t, s)
|
||||
s.Shutdown()
|
||||
|
||||
// restart the server
|
||||
s, _ = RunServerWithConfig(cf)
|
||||
if !s.Running() {
|
||||
t.Fatalf("Server should be running")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJetStreamTPMAll(t *testing.T) {
|
||||
fileName := getTPMFileName(t)
|
||||
|
||||
// TODO: When the CI/CD environment supports updating the TPM,
|
||||
// expand this test with the SRK password.
|
||||
cf := createConfFile(t, []byte(fmt.Sprintf(jsTPMConfigAllFields,
|
||||
getTPMFileName(t), fileName, 19, "")))
|
||||
|
||||
s, _ := RunServerWithConfig(cf)
|
||||
defer s.Shutdown()
|
||||
|
||||
checkSendMessage(t, s)
|
||||
s.Shutdown()
|
||||
|
||||
// restart the server.
|
||||
s, _ = RunServerWithConfig(cf)
|
||||
if s.Running() == false {
|
||||
t.Fatalf("Server should be running")
|
||||
}
|
||||
defer s.Shutdown()
|
||||
checkReceiveMessage(t, s)
|
||||
}
|
||||
|
||||
func TestJetStreamInvalidConfig(t *testing.T) {
|
||||
cf := createConfFile(t, []byte(fmt.Sprintf(jsTPMConfigInvalidBothOptionsSet,
|
||||
getTPMFileName(t))))
|
||||
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
t.Fatalf("Expected server panic, unexpected start.")
|
||||
}
|
||||
}()
|
||||
s, _ := RunServerWithConfig(cf)
|
||||
if s.Running() == true {
|
||||
s.Shutdown()
|
||||
t.Fatalf("Server should NOT be running")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user