A node's serving key is stored in the format a server reads
PKCS#8 PEM, not this host's own base64. The mesh delivers a PEM certificate beside it and every TLS server there is reads PEM: nginx's ssl_certificate_key, Go's LoadX509KeyPair, openssl s_server. Stored the other way the file was intact, present, correctly permissioned, and unusable — the machine failed at the moment something connected, which the lab found by connecting. A key in the old encoding is refused by name rather than called corrupt: it is replaced by enrolling again, and that is a different remedy from a damaged file.
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package identity
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// The whole reason the file exists is that something else reads it.
|
||||
//
|
||||
// A key in this host's own encoding is intact, unusable, and indistinguishable from a working one
|
||||
// until the moment a client connects — the mesh delivers the certificate, the file is there with
|
||||
// the right permissions, and the server will not start.
|
||||
func TestTheServingKeyIsWrittenInTheFormatAServerReads(t *testing.T) {
|
||||
made, err := GenerateServingKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
path := filepath.Join(t.TempDir(), "serving.key")
|
||||
if err := WriteServingKey(path, made); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block, _ := pem.Decode(raw)
|
||||
if block == nil {
|
||||
t.Fatalf("the serving key is not PEM, so nothing serving TLS can read it:\n%s", raw)
|
||||
}
|
||||
parsed, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
t.Fatalf("the serving key is PEM and not a key: %v", err)
|
||||
}
|
||||
// And it is the key that was written, not merely a key — a file that round-trips through the
|
||||
// wrong half would certify a public key the machine cannot prove it holds.
|
||||
if _, isEd25519 := parsed.(ed25519.PrivateKey); !isEd25519 {
|
||||
t.Fatalf("the serving key is a %T", parsed)
|
||||
}
|
||||
read, err := LoadServingKey(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if read.Public != made.Public {
|
||||
t.Fatal("the key read back is not the key written, so the mesh would certify the wrong one")
|
||||
}
|
||||
}
|
||||
|
||||
// The old encoding is refused by name, because the remedy is different from a corrupt file and
|
||||
// the difference is invisible from the outside.
|
||||
func TestAServingKeyInTheOldEncodingIsNamedRatherThanCalledCorrupt(t *testing.T) {
|
||||
made, err := GenerateServingKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
path := filepath.Join(t.TempDir(), "serving.key")
|
||||
if err := os.WriteFile(path, []byte(made.Private+"\n"), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = LoadServingKey(path)
|
||||
if err == nil {
|
||||
t.Fatal("a key nothing can serve with was accepted")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "enrolling again") {
|
||||
t.Fatalf("refused without naming the remedy: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user