1
18
19 package credentials
20
21 import (
22 "crypto/tls"
23 "crypto/x509"
24 "encoding/pem"
25 "net/url"
26 "os"
27 "testing"
28
29 "google.golang.org/grpc/internal/grpctest"
30 "google.golang.org/grpc/testdata"
31 )
32
33 const wantURI = "spiffe://foo.bar.com/client/workload/1"
34
35 type s struct {
36 grpctest.Tester
37 }
38
39 func Test(t *testing.T) {
40 grpctest.RunSubTests(t, s{})
41 }
42
43 func (s) TestSPIFFEIDFromState(t *testing.T) {
44 tests := []struct {
45 name string
46 urls []*url.URL
47
48 wantID bool
49 }{
50 {
51 name: "empty URIs",
52 urls: []*url.URL{},
53 wantID: false,
54 },
55 {
56 name: "good SPIFFE ID",
57 urls: []*url.URL{
58 {
59 Scheme: "spiffe",
60 Host: "foo.bar.com",
61 Path: "workload/wl1",
62 RawPath: "workload/wl1",
63 },
64 },
65 wantID: true,
66 },
67 {
68 name: "invalid host",
69 urls: []*url.URL{
70 {
71 Scheme: "spiffe",
72 Host: "",
73 Path: "workload/wl1",
74 RawPath: "workload/wl1",
75 },
76 },
77 wantID: false,
78 },
79 {
80 name: "invalid path",
81 urls: []*url.URL{
82 {
83 Scheme: "spiffe",
84 Host: "foo.bar.com",
85 Path: "",
86 RawPath: "",
87 },
88 },
89 wantID: false,
90 },
91 {
92 name: "large path",
93 urls: []*url.URL{
94 {
95 Scheme: "spiffe",
96 Host: "foo.bar.com",
97 Path: string(make([]byte, 2050)),
98 RawPath: string(make([]byte, 2050)),
99 },
100 },
101 wantID: false,
102 },
103 {
104 name: "large host",
105 urls: []*url.URL{
106 {
107 Scheme: "spiffe",
108 Host: string(make([]byte, 256)),
109 Path: "workload/wl1",
110 RawPath: "workload/wl1",
111 },
112 },
113 wantID: false,
114 },
115 {
116 name: "multiple URI SANs",
117 urls: []*url.URL{
118 {
119 Scheme: "spiffe",
120 Host: "foo.bar.com",
121 Path: "workload/wl1",
122 RawPath: "workload/wl1",
123 },
124 {
125 Scheme: "spiffe",
126 Host: "bar.baz.com",
127 Path: "workload/wl2",
128 RawPath: "workload/wl2",
129 },
130 {
131 Scheme: "https",
132 Host: "foo.bar.com",
133 Path: "workload/wl1",
134 RawPath: "workload/wl1",
135 },
136 },
137 wantID: false,
138 },
139 {
140 name: "multiple URI SANs without SPIFFE ID",
141 urls: []*url.URL{
142 {
143 Scheme: "https",
144 Host: "foo.bar.com",
145 Path: "workload/wl1",
146 RawPath: "workload/wl1",
147 },
148 {
149 Scheme: "ssh",
150 Host: "foo.bar.com",
151 Path: "workload/wl1",
152 RawPath: "workload/wl1",
153 },
154 },
155 wantID: false,
156 },
157 {
158 name: "multiple URI SANs with one SPIFFE ID",
159 urls: []*url.URL{
160 {
161 Scheme: "spiffe",
162 Host: "foo.bar.com",
163 Path: "workload/wl1",
164 RawPath: "workload/wl1",
165 },
166 {
167 Scheme: "https",
168 Host: "foo.bar.com",
169 Path: "workload/wl1",
170 RawPath: "workload/wl1",
171 },
172 },
173 wantID: false,
174 },
175 }
176 for _, tt := range tests {
177 t.Run(tt.name, func(t *testing.T) {
178 state := tls.ConnectionState{PeerCertificates: []*x509.Certificate{{URIs: tt.urls}}}
179 id := SPIFFEIDFromState(state)
180 if got, want := id != nil, tt.wantID; got != want {
181 t.Errorf("want wantID = %v, but SPIFFE ID is %v", want, id)
182 }
183 })
184 }
185 }
186
187 func (s) TestSPIFFEIDFromCert(t *testing.T) {
188 tests := []struct {
189 name string
190 dataPath string
191
192 wantID bool
193 }{
194 {
195 name: "good certificate with SPIFFE ID",
196 dataPath: "x509/spiffe_cert.pem",
197 wantID: true,
198 },
199 {
200 name: "bad certificate with SPIFFE ID and another URI",
201 dataPath: "x509/multiple_uri_cert.pem",
202 wantID: false,
203 },
204 {
205 name: "certificate without SPIFFE ID",
206 dataPath: "x509/client1_cert.pem",
207 wantID: false,
208 },
209 }
210 for _, tt := range tests {
211 t.Run(tt.name, func(t *testing.T) {
212 data, err := os.ReadFile(testdata.Path(tt.dataPath))
213 if err != nil {
214 t.Fatalf("os.ReadFile(%s) failed: %v", testdata.Path(tt.dataPath), err)
215 }
216 block, _ := pem.Decode(data)
217 if block == nil {
218 t.Fatalf("Failed to parse the certificate: byte block is nil")
219 }
220 cert, err := x509.ParseCertificate(block.Bytes)
221 if err != nil {
222 t.Fatalf("x509.ParseCertificate(%b) failed: %v", block.Bytes, err)
223 }
224 uri := SPIFFEIDFromCert(cert)
225 if (uri != nil) != tt.wantID {
226 t.Fatalf("wantID got and want mismatch, got %t, want %t", uri != nil, tt.wantID)
227 }
228 if uri != nil && uri.String() != wantURI {
229 t.Fatalf("SPIFFE ID not expected, got %s, want %s", uri.String(), wantURI)
230 }
231 })
232 }
233 }
234
View as plain text