package identity import ( "context" "crypto/ed25519" "crypto/rand" "crypto/x509" "encoding/base64" "encoding/pem" "strings" "sync" "testing" ) // The authority that certifies names inside the mesh. // // Asserted by verifying, not by inspecting: a certificate that parses and does not chain is a // certificate that fails at the moment something connects, which is the worst place to find out. func aServingKey(t *testing.T) (public string, private ed25519.PrivateKey) { t.Helper() pub, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { t.Fatal(err) } return base64.StdEncoding.EncodeToString(pub), priv } func parsed(t *testing.T, certificate string) *x509.Certificate { t.Helper() block, _ := pem.Decode([]byte(certificate)) if block == nil { t.Fatal("not a certificate") } got, err := x509.ParseCertificate(block.Bytes) if err != nil { t.Fatal(err) } return got } func TestACertificateChainsToTheMeshsOwnAuthority(t *testing.T) { ident := fresh(t) ctx := context.Background() public, _ := aServingKey(t) certificate, err := ident.Certify(ctx, "workstation", "workstation.internal", public) if err != nil { t.Fatal(err) } authority, err := ident.EstablishAuthority(ctx) if err != nil { t.Fatal(err) } roots := x509.NewCertPool() if !roots.AppendCertsFromPEM([]byte(authority.Certificate)) { t.Fatal("the mesh's authority is not usable as a root") } if _, err := parsed(t, certificate).Verify(x509.VerifyOptions{ Roots: roots, DNSName: "workstation.internal", }); err != nil { t.Fatalf("what the mesh issued does not verify against the mesh: %v", err) } } func TestTheNameIsWhereEverythingLooksForIt(t *testing.T) { // A certificate carrying the name only in its common name is one every modern client refuses. ident := fresh(t) public, _ := aServingKey(t) certificate, err := ident.Certify(context.Background(), "a", "a.internal", public) if err != nil { t.Fatal(err) } got := parsed(t, certificate) if len(got.DNSNames) != 1 || got.DNSNames[0] != "a.internal" { t.Fatalf("the name is not in the subject alternative names: %v", got.DNSNames) } } func TestItCertifiesTheKeyTheNodeGeneratedAndNoOther(t *testing.T) { // A certificate authority's whole job is to say "this name belongs to the holder of this // key". One that made the key would be saying something about a key it also holds. ident := fresh(t) public, private := aServingKey(t) certificate, err := ident.Certify(context.Background(), "a", "a.internal", public) if err != nil { t.Fatal(err) } inside, ok := parsed(t, certificate).PublicKey.(ed25519.PublicKey) if !ok { t.Fatalf("the certificate carries a %T", parsed(t, certificate).PublicKey) } if !inside.Equal(private.Public()) { t.Fatal("the certificate is for a key the node does not hold") } } func TestAnAuthorityIsEstablishedOnceAndKept(t *testing.T) { // Two authorities and nothing says which certificate to believe. ident := fresh(t) ctx := context.Background() first, err := ident.EstablishAuthority(ctx) if err != nil { t.Fatal(err) } second, err := ident.EstablishAuthority(ctx) if err != nil { t.Fatal(err) } if first.Certificate != second.Certificate { t.Fatal("asking twice made a second authority") } } func TestSomethingThatIsNotAServingKeyIsRefused(t *testing.T) { ident := fresh(t) for _, bad := range []string{"", "not-base64!", base64.StdEncoding.EncodeToString([]byte("short"))} { if _, err := ident.Certify(context.Background(), "a", "a.internal", bad); err == nil { t.Fatalf("%q was certified", bad) } } } func TestTheAuthorityCannotBeUsedToMakeAnotherAuthority(t *testing.T) { // An authority that could sign another is one that can be delegated without anybody deciding // to. The path length says it cannot. ident := fresh(t) authority, err := ident.EstablishAuthority(context.Background()) if err != nil { t.Fatal(err) } got := parsed(t, authority.Certificate) if !got.IsCA { t.Fatal("the authority is not an authority") } if got.MaxPathLen != 0 || !got.MaxPathLenZero { t.Fatalf("the authority may sign another authority: path length %d", got.MaxPathLen) } } func TestACertificateFromAnotherMeshDoesNotVerify(t *testing.T) { // The whole point of two authorities being separate: one mesh's certificate means nothing to // another, and the check that says so is the one that must not be skipped. one, two := fresh(t), fresh(t) public, _ := aServingKey(t) certificate, err := one.Certify(context.Background(), "a", "a.internal", public) if err != nil { t.Fatal(err) } other, err := two.EstablishAuthority(context.Background()) if err != nil { t.Fatal(err) } roots := x509.NewCertPool() roots.AppendCertsFromPEM([]byte(other.Certificate)) if _, err := parsed(t, certificate).Verify(x509.VerifyOptions{ Roots: roots, DNSName: "a.internal", }); err == nil { t.Fatal("another mesh's certificate verified") } else if !strings.Contains(err.Error(), "authority") && !strings.Contains(err.Error(), "signed") { t.Fatalf("refused for the wrong reason: %v", err) } } func TestTwoProcessesStartingTogetherAgreeOnOneAuthority(t *testing.T) { // A restart while another copy is coming up. Both find nothing and both generate; only one // insert may survive, and the loser must read back the winner rather than return the // authority it generated and did not store — a mesh with two authorities has certificates // half its machines refuse. ident := fresh(t) var wg sync.WaitGroup authorities := make([]Authority, 6) errs := make([]error, 6) for i := range authorities { wg.Add(1) go func(i int) { defer wg.Done() authorities[i], errs[i] = ident.EstablishAuthority(context.Background()) }(i) } wg.Wait() for i, err := range errs { if err != nil { t.Fatalf("establish %d failed: %v", i, err) } } for i, a := range authorities { if a.Certificate != authorities[0].Certificate { t.Errorf("establish %d has a different authority from establish 0", i) } } var count int if err := ident.store.Pool().QueryRow(t.Context(), `select count(*) from authority`).Scan(&count); err != nil { t.Fatal(err) } if count != 1 { t.Errorf("%d authorities exist; exactly one may", count) } }