@@ -8,13 +8,15 @@ import (
8
8
"net/http"
9
9
"net/http/httptest"
10
10
"reflect"
11
+ "strings"
11
12
"sync"
12
13
"testing"
13
14
"time"
14
15
15
16
"github.com/pkg/errors"
16
17
"github.com/smallstep/certificates/api"
17
18
"github.com/smallstep/certificates/authority"
19
+ "github.com/smallstep/certificates/errs"
18
20
"go.step.sm/crypto/jose"
19
21
"go.step.sm/crypto/randutil"
20
22
)
@@ -74,6 +76,30 @@ func startCAServer(configFile string) (*CA, string, error) {
74
76
return ca , caURL , nil
75
77
}
76
78
79
+ func mTLSMiddleware (next http.Handler , nonAuthenticatedPaths ... string ) http.Handler {
80
+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
81
+ if r .URL .Path == "/version" {
82
+ api .JSON (w , api.VersionResponse {
83
+ Version : "test" ,
84
+ RequireClientAuthentication : true ,
85
+ })
86
+ return
87
+ }
88
+
89
+ for _ , s := range nonAuthenticatedPaths {
90
+ if strings .HasPrefix (r .URL .Path , s ) || strings .HasPrefix (r .URL .Path , "/1.0" + s ) {
91
+ next .ServeHTTP (w , r )
92
+ }
93
+ }
94
+ isMTLS := r .TLS != nil && len (r .TLS .PeerCertificates ) > 0
95
+ if ! isMTLS {
96
+ api .WriteError (w , errs .Unauthorized ("missing peer certificate" ))
97
+ } else {
98
+ next .ServeHTTP (w , r )
99
+ }
100
+ })
101
+ }
102
+
77
103
func generateBootstrapToken (ca , subject , sha string ) string {
78
104
now := time .Now ()
79
105
jwk , err := jose .ReadKey ("testdata/secrets/ott_mariano_priv.jwk" , jose .WithPassword ([]byte ("password" )))
@@ -171,6 +197,15 @@ func TestBootstrapServerWithoutMTLS(t *testing.T) {
171
197
token := func () string {
172
198
return generateBootstrapToken (srv .URL , "subject" , "ef742f95dc0d8aa82d3cca4017af6dac3fce84290344159891952d18c53eefe7" )
173
199
}
200
+
201
+ mtlsServer := startCABootstrapServer ()
202
+ next := mtlsServer .Config .Handler
203
+ mtlsServer .Config .Handler = mTLSMiddleware (next , "/root/" , "/sign" )
204
+ defer mtlsServer .Close ()
205
+ mtlsToken := func () string {
206
+ return generateBootstrapToken (mtlsServer .URL , "subject" , "ef742f95dc0d8aa82d3cca4017af6dac3fce84290344159891952d18c53eefe7" )
207
+ }
208
+
174
209
type args struct {
175
210
ctx context.Context
176
211
token string
@@ -182,6 +217,7 @@ func TestBootstrapServerWithoutMTLS(t *testing.T) {
182
217
wantErr bool
183
218
}{
184
219
{"ok" , args {context .Background (), token (), & http.Server {}}, false },
220
+ {"ok mtls" , args {context .Background (), mtlsToken (), & http.Server {}}, false },
185
221
{"fail" , args {context .Background (), "bad-token" , & http.Server {}}, true },
186
222
{"fail with TLSConfig" , args {context .Background (), token (), & http.Server {TLSConfig : & tls.Config {}}}, true },
187
223
}
@@ -217,6 +253,15 @@ func TestBootstrapServerWithMTLS(t *testing.T) {
217
253
token := func () string {
218
254
return generateBootstrapToken (srv .URL , "subject" , "ef742f95dc0d8aa82d3cca4017af6dac3fce84290344159891952d18c53eefe7" )
219
255
}
256
+
257
+ mtlsServer := startCABootstrapServer ()
258
+ next := mtlsServer .Config .Handler
259
+ mtlsServer .Config .Handler = mTLSMiddleware (next , "/root/" , "/sign" )
260
+ defer mtlsServer .Close ()
261
+ mtlsToken := func () string {
262
+ return generateBootstrapToken (mtlsServer .URL , "subject" , "ef742f95dc0d8aa82d3cca4017af6dac3fce84290344159891952d18c53eefe7" )
263
+ }
264
+
220
265
type args struct {
221
266
ctx context.Context
222
267
token string
@@ -228,6 +273,7 @@ func TestBootstrapServerWithMTLS(t *testing.T) {
228
273
wantErr bool
229
274
}{
230
275
{"ok" , args {context .Background (), token (), & http.Server {}}, false },
276
+ {"ok mtls" , args {context .Background (), mtlsToken (), & http.Server {}}, false },
231
277
{"fail" , args {context .Background (), "bad-token" , & http.Server {}}, true },
232
278
{"fail with TLSConfig" , args {context .Background (), token (), & http.Server {TLSConfig : & tls.Config {}}}, true },
233
279
}
@@ -263,6 +309,15 @@ func TestBootstrapClient(t *testing.T) {
263
309
token := func () string {
264
310
return generateBootstrapToken (srv .URL , "subject" , "ef742f95dc0d8aa82d3cca4017af6dac3fce84290344159891952d18c53eefe7" )
265
311
}
312
+
313
+ mtlsServer := startCABootstrapServer ()
314
+ next := mtlsServer .Config .Handler
315
+ mtlsServer .Config .Handler = mTLSMiddleware (next , "/root/" , "/sign" )
316
+ defer mtlsServer .Close ()
317
+ mtlsToken := func () string {
318
+ return generateBootstrapToken (mtlsServer .URL , "subject" , "ef742f95dc0d8aa82d3cca4017af6dac3fce84290344159891952d18c53eefe7" )
319
+ }
320
+
266
321
type args struct {
267
322
ctx context.Context
268
323
token string
@@ -273,6 +328,7 @@ func TestBootstrapClient(t *testing.T) {
273
328
wantErr bool
274
329
}{
275
330
{"ok" , args {context .Background (), token ()}, false },
331
+ {"ok mtls" , args {context .Background (), mtlsToken ()}, false },
276
332
{"fail" , args {context .Background (), "bad-token" }, true },
277
333
}
278
334
for _ , tt := range tests {
@@ -541,6 +597,15 @@ func TestBootstrapListener(t *testing.T) {
541
597
token := func () string {
542
598
return generateBootstrapToken (srv .URL , "127.0.0.1" , "ef742f95dc0d8aa82d3cca4017af6dac3fce84290344159891952d18c53eefe7" )
543
599
}
600
+
601
+ mtlsServer := startCABootstrapServer ()
602
+ next := mtlsServer .Config .Handler
603
+ mtlsServer .Config .Handler = mTLSMiddleware (next , "/root/" , "/sign" )
604
+ defer mtlsServer .Close ()
605
+ mtlsToken := func () string {
606
+ return generateBootstrapToken (mtlsServer .URL , "subject" , "ef742f95dc0d8aa82d3cca4017af6dac3fce84290344159891952d18c53eefe7" )
607
+ }
608
+
544
609
type args struct {
545
610
token string
546
611
}
@@ -550,6 +615,7 @@ func TestBootstrapListener(t *testing.T) {
550
615
wantErr bool
551
616
}{
552
617
{"ok" , args {token ()}, false },
618
+ {"ok mtls" , args {mtlsToken ()}, false },
553
619
{"fail" , args {"bad-token" }, true },
554
620
}
555
621
for _ , tt := range tests {
0 commit comments