blob: da8dee91b5c77628b58dbbef8eec7be0b385791c [file] [log] [blame]
Serge Bazanski52538842021-08-11 16:22:41 +02001package pki
2
3import (
4 "bytes"
5 "context"
6 "crypto/ed25519"
7 "crypto/rand"
8 "crypto/x509"
9 "testing"
10
11 "go.etcd.io/etcd/integration"
12)
13
14// TestManaged ensures Managed Certificates work, including re-ensuring
15// certificates with the same data and issuing subordinate certificates.
16func TestManaged(t *testing.T) {
17 cluster := integration.NewClusterV3(nil, &integration.ClusterConfig{
18 Size: 1,
19 })
20 cl := cluster.Client(0)
21 defer cluster.Terminate(nil)
22 ctx, ctxC := context.WithCancel(context.Background())
23 defer ctxC()
24 ns := Namespaced("/test-managed/")
25
26 // Test CA certificate issuance.
27 ca := &Certificate{
28 Namespace: &ns,
29 Issuer: SelfSigned,
30 Name: "ca",
31 Template: CA("Test CA"),
32 }
33 caBytes, err := ca.Ensure(ctx, cl)
34 if err != nil {
35 t.Fatalf("Failed to Ensure CA: %v", err)
36 }
37 caCert, err := x509.ParseCertificate(caBytes)
38 if err != nil {
39 t.Fatalf("Failed to parse newly emited CA cert: %v", err)
40 }
41 if !caCert.IsCA {
42 t.Errorf("Newly emitted CA cert is not CA")
43 }
44 if ca.PublicKey == nil {
45 t.Errorf("Newly emitted CA cert has no public key")
46 }
47 if ca.PrivateKey == nil {
48 t.Errorf("Newly emitted CA cert has no public key")
49 }
50
51 // Re-emitting CA certificate with same parameters should return exact same
52 // data.
53 ca2 := &Certificate{
54 Namespace: &ns,
55 Issuer: SelfSigned,
56 Name: "ca",
57 Template: CA("Test CA"),
58 }
59 caBytes2, err := ca2.Ensure(ctx, cl)
60 if err != nil {
61 t.Fatalf("Failed to re-Ensure CA: %v", err)
62 }
63 if !bytes.Equal(caBytes, caBytes2) {
64 t.Errorf("New CA has different x509 certificate")
65 }
66 if !bytes.Equal(ca.PublicKey, ca2.PublicKey) {
67 t.Errorf("New CA has different public key")
68 }
69 if !bytes.Equal(ca.PrivateKey, ca2.PrivateKey) {
70 t.Errorf("New CA has different private key")
71 }
72
73 // Emitting a subordinate certificate should work.
74 client := &Certificate{
75 Namespace: &ns,
76 Issuer: ca2,
77 Name: "client",
78 Template: Client("foo", nil),
79 }
80 clientBytes, err := client.Ensure(ctx, cl)
81 if err != nil {
82 t.Fatalf("Failed to ensure client certificate: %v", err)
83 }
84 clientCert, err := x509.ParseCertificate(clientBytes)
85 if err != nil {
86 t.Fatalf("Failed to parse newly emitted client certificate: %v", err)
87 }
88 if clientCert.IsCA {
89 t.Errorf("New client cert is CA")
90 }
91 if want, got := "foo", clientCert.Subject.CommonName; want != got {
92 t.Errorf("New client CN should be %q, got %q", want, got)
93 }
94 if want, got := caCert.Subject.String(), clientCert.Issuer.String(); want != got {
95 t.Errorf("New client issuer should be %q, got %q", want, got)
96 }
97}
98
99// TestExternal ensures External certificates work correctly, including
100// re-Ensuring certificates with the same public key, and attempting to re-issue
101// the same certificate with a different public key (which should fail).
102func TestExternal(t *testing.T) {
103 cluster := integration.NewClusterV3(nil, &integration.ClusterConfig{
104 Size: 1,
105 })
106 cl := cluster.Client(0)
107 defer cluster.Terminate(nil)
108 ctx, ctxC := context.WithCancel(context.Background())
109 defer ctxC()
110 ns := Namespaced("/test-external/")
111
112 ca := &Certificate{
113 Namespace: &ns,
114 Issuer: SelfSigned,
115 Name: "ca",
116 Template: CA("Test CA"),
117 }
118
119 // Issuing an external certificate should work.
120 pk, _, err := ed25519.GenerateKey(rand.Reader)
121 if err != nil {
122 t.Fatalf("GenerateKey: %v", err)
123 }
124 server := &Certificate{
125 Namespace: &ns,
126 Issuer: ca,
127 Name: "server",
128 Template: Server([]string{"server"}, nil),
129 Mode: CertificateExternal,
130 PublicKey: pk,
131 }
132 serverBytes, err := server.Ensure(ctx, cl)
133 if err != nil {
134 t.Fatalf("Failed to Ensure server certificate: %v", err)
135 }
136
137 // Issuing an external certificate with the same name but different public key
138 // should fail.
139 pk2, _, err := ed25519.GenerateKey(rand.Reader)
140 if err != nil {
141 t.Fatalf("GenerateKey: %v", err)
142 }
143 server2 := &Certificate{
144 Namespace: &ns,
145 Issuer: ca,
146 Name: "server",
147 Template: Server([]string{"server"}, nil),
148 Mode: CertificateExternal,
149 PublicKey: pk2,
150 }
151 if _, err := server2.Ensure(ctx, cl); err == nil {
152 t.Fatalf("Issuing server certificate with different public key should have failed")
153 }
154
155 // Issuing the external certificate with the same name and same public key
156 // should work and yield the same x509 bytes.
157 server3 := &Certificate{
158 Namespace: &ns,
159 Issuer: ca,
160 Name: "server",
161 Template: Server([]string{"server"}, nil),
162 Mode: CertificateExternal,
163 PublicKey: pk,
164 }
165 serverBytes3, err := server3.Ensure(ctx, cl)
166 if err != nil {
167 t.Fatalf("Failed to re-Ensure server certificate: %v", err)
168 }
169 if !bytes.Equal(serverBytes, serverBytes3) {
170 t.Errorf("New server certificate has different x509 certificate")
171 }
172}