Merge lp:~pedronis/ubuntu-push/http-ssl into lp:ubuntu-push/automatic

Proposed by Samuele Pedroni
Status: Merged
Approved by: Samuele Pedroni
Approved revision: 328
Merged at revision: 333
Proposed branch: lp:~pedronis/ubuntu-push/http-ssl
Merge into: lp:ubuntu-push/automatic
Diff against target: 655 lines (+198/-138)
17 files modified
client/session/session_test.go (+4/-25)
sampleconfigs/dev.json (+1/-1)
server/acceptance/acceptance_test.go (+1/-1)
server/acceptance/ssl/README (+1/-1)
server/acceptance/ssl/testing.cert (+7/-7)
server/acceptance/ssl/testing.key (+7/-7)
server/acceptance/suites/broadcast.go (+1/-1)
server/acceptance/suites/suite.go (+1/-1)
server/config_test.go (+12/-11)
server/dev/server.go (+2/-2)
server/listener/listener.go (+4/-13)
server/listener/listener_test.go (+9/-17)
server/runner_devices.go (+2/-29)
server/runner_http.go (+6/-1)
server/runner_test.go (+45/-6)
server/tlsconfig.go (+53/-0)
testing/tls.go (+42/-15)
To merge this branch: bzr merge lp:~pedronis/ubuntu-push/http-ssl
Reviewer Review Type Date Requested Status
Guillermo Gonzalez Approve
Review via email: mp+233403@code.launchpad.net

Commit message

- let the http runner serve over tls optionally
- more realistic testing cert/key
- review how we setup tls in tests

Description of the change

- let the http runner serve over tls optionally
- more realistic testing cert/key
- review how we setup tls in tests

To post a comment you must log in.
lp:~pedronis/ubuntu-push/http-ssl updated
327. By Samuele Pedroni

comment tweak

328. By Samuele Pedroni

fix, thanks verterok

Revision history for this message
Guillermo Gonzalez (verterok) wrote :

looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'client/session/session_test.go'
2--- client/session/session_test.go 2014-08-26 16:05:28 +0000
3+++ client/session/session_test.go 2014-09-04 19:21:18 +0000
4@@ -1489,14 +1489,7 @@
5
6 func (cs *clientSessionSuite) TestDialBadServerName(c *C) {
7 // a borked server name
8- cert, err := tls.X509KeyPair(helpers.TestCertPEMBlock, helpers.TestKeyPEMBlock)
9- c.Assert(err, IsNil)
10- tlsCfg := &tls.Config{
11- Certificates: []tls.Certificate{cert},
12- SessionTicketsDisabled: true,
13- }
14-
15- lst, err := tls.Listen("tcp", "localhost:0", tlsCfg)
16+ lst, err := tls.Listen("tcp", "localhost:0", helpers.TestTLSServerConfig)
17 c.Assert(err, IsNil)
18 // advertise
19 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
20@@ -1541,19 +1534,12 @@
21
22 func (cs *clientSessionSuite) TestDialWorks(c *C) {
23 // happy path thoughts
24- cert, err := tls.X509KeyPair(helpers.TestCertPEMBlock, helpers.TestKeyPEMBlock)
25- c.Assert(err, IsNil)
26- tlsCfg := &tls.Config{
27- Certificates: []tls.Certificate{cert},
28- SessionTicketsDisabled: true,
29- }
30-
31- lst, err := tls.Listen("tcp", "localhost:0", tlsCfg)
32+ lst, err := tls.Listen("tcp", "localhost:0", helpers.TestTLSServerConfig)
33 c.Assert(err, IsNil)
34 // advertise
35 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
36 b, err := json.Marshal(map[string]interface{}{
37- "domain": "localhost",
38+ "domain": "push-delivery",
39 "hosts": []string{"nowhere", lst.Addr().String()},
40 })
41 if err != nil {
42@@ -1649,14 +1635,7 @@
43
44 func (cs *clientSessionSuite) TestDialWorksDirect(c *C) {
45 // happy path thoughts
46- cert, err := tls.X509KeyPair(helpers.TestCertPEMBlock, helpers.TestKeyPEMBlock)
47- c.Assert(err, IsNil)
48- tlsCfg := &tls.Config{
49- Certificates: []tls.Certificate{cert},
50- SessionTicketsDisabled: true,
51- }
52-
53- lst, err := tls.Listen("tcp", "localhost:0", tlsCfg)
54+ lst, err := tls.Listen("tcp", "localhost:0", helpers.TestTLSServerConfig)
55 c.Assert(err, IsNil)
56 sess, err := NewSession(lst.Addr().String(), dialTestConf, "wah", cs.lvls, cs.log)
57 c.Assert(err, IsNil)
58
59=== modified file 'sampleconfigs/dev.json'
60--- sampleconfigs/dev.json 2014-07-15 17:14:07 +0000
61+++ sampleconfigs/dev.json 2014-09-04 19:21:18 +0000
62@@ -10,5 +10,5 @@
63 "http_read_timeout": "5s",
64 "http_write_timeout": "5s",
65 "max_notifications_per_app": 25,
66- "delivery_domain": "localhost"
67+ "delivery_domain": "push-delivery"
68 }
69
70=== modified file 'server/acceptance/acceptance_test.go'
71--- server/acceptance/acceptance_test.go 2014-05-02 09:56:49 +0000
72+++ server/acceptance/acceptance_test.go 2014-09-04 19:21:18 +0000
73@@ -34,7 +34,7 @@
74 cfg := make(map[string]interface{})
75 suites.FillServerConfig(cfg, addr)
76 suites.FillHTTPServerConfig(cfg, httpAddr)
77- cfg["delivery_domain"] = "localhost"
78+ cfg["delivery_domain"] = "push-delivery"
79 return cfg
80 }
81
82
83=== modified file 'server/acceptance/ssl/README'
84--- server/acceptance/ssl/README 2014-02-21 16:17:28 +0000
85+++ server/acceptance/ssl/README 2014-09-04 19:21:18 +0000
86@@ -3,6 +3,6 @@
87
88 Generated with:
89
90- go run /usr/lib/go/src/pkg/crypto/tls/generate_cert.go -ca -host localhost -rsa-bits 512 -duration 87600h
91+ go run /usr/lib/go/src/pkg/crypto/tls/generate_cert.go -ca -host push-delivery -rsa-bits 512 -duration 87600h
92
93 and then renamed.
94
95=== modified file 'server/acceptance/ssl/testing.cert'
96--- server/acceptance/ssl/testing.cert 2014-01-14 15:35:20 +0000
97+++ server/acceptance/ssl/testing.cert 2014-09-04 19:21:18 +0000
98@@ -1,10 +1,10 @@
99 -----BEGIN CERTIFICATE-----
100 MIIBYzCCAQ+gAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
101-bzAeFw0xMzEyMTkyMDU1NDNaFw0yMzEyMTcyMDU1NDNaMBIxEDAOBgNVBAoTB0Fj
102-bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAPw+niki17X2qALE2A2AzE1q5dvK
103-9CI4OduRtT9IgbFLC6psqAT21NA+QbY17nWSSpyP65zkMkwKXrbDzstwLPkCAwEA
104-AaNUMFIwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
105-EwEB/wQFMAMBAf8wGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMAsGCSqGSIb3
106-DQEBBQNBAFqiVI+Km2XPSO+pxITaPvhmuzg+XG3l1+2di3gL+HlDobocjBqRctRU
107-YySO32W07acjGJmCHUKpCJuq9X8hpmk=
108+bzAeFw0xNDA4MjkxMjQyMDFaFw0yNDA4MjYxMjQyMDFaMBIxEDAOBgNVBAoTB0Fj
109+bWUgQ28wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA1FT6lkow0eky+Dnj2Z4nTrTF
110+DgcKOt9Wr4B4gRH1bWmRqScOPxyHA5YodN7O1w8X8sdWko9puf59I1sWWr5LNwID
111+AQABo1IwUDAOBgNVHQ8BAf8EBAMCAKQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYD
112+VR0TAQH/BAUwAwEB/zAYBgNVHREEETAPgg1wdXNoLWRlbGl2ZXJ5MAsGCSqGSIb3
113+DQEBBQNBABtWCdMFkhIO8+oM3vugOWle9WJZ1FCRWD+cMl76mI1lhmNF4lvEZG47
114+xUjekA1+heU39WpOEzZSybrOdiEaGbI=
115 -----END CERTIFICATE-----
116
117=== modified file 'server/acceptance/ssl/testing.key'
118--- server/acceptance/ssl/testing.key 2014-01-14 15:35:20 +0000
119+++ server/acceptance/ssl/testing.key 2014-09-04 19:21:18 +0000
120@@ -1,9 +1,9 @@
121 -----BEGIN RSA PRIVATE KEY-----
122-MIIBPAIBAAJBAPw+niki17X2qALE2A2AzE1q5dvK9CI4OduRtT9IgbFLC6psqAT2
123-1NA+QbY17nWSSpyP65zkMkwKXrbDzstwLPkCAwEAAQJAKwXbIBULScP6QA6m8xam
124-wgWbkvN41GVWqPafPV32kPBvKwSc+M1e+JR7g3/xPZE7TCELcfYi4yXEHZZI3Pbh
125-oQIhAP/UsgJbsfH1GFv8Y8qGl5l/kmwwkwHhuKvEC87Yur9FAiEA/GlQv3ZfaXnT
126-lcCFT0aL02O0RDiRYyMUG/JAZQJs6CUCIQCHO5SZYIUwxIGK5mCNxxXOAzyQSiD7
127-hqkKywf+4FvfDQIhALa0TLyqJFom0t7c4iIGAIRc8UlIYQSPiajI64+x9775AiEA
128-0v4fgSK/Rq059zW1753JjuB6aR0Uh+3RqJII4dUR1Wg=
129+MIIBOgIBAAJBANRU+pZKMNHpMvg549meJ060xQ4HCjrfVq+AeIER9W1pkaknDj8c
130+hwOWKHTeztcPF/LHVpKPabn+fSNbFlq+SzcCAwEAAQJBAIOO+4xu/3yv/rKqO7C0
131+Oyqa+pVMa1w60R0AfqmKFQTqiTgevM77uqjpW1+t0hpK20nyj6MUIPaL+9kZgp7t
132+mnECIQDqw79PXSzudf10XGy9ve5bRazINHxQYgJ7FvlTT6JhdQIhAOeJxq9zcKni
133+69ueO1ualz0hn8w6uHPsG9FlZ8C+7Jh7AiAWJgebjjfZ+4nA+6NKt2uQct9dOA5u
134+awC+6ij1ojK4rQIgNEqAbcWDj0qpe8sLms+aEntSjJxCZiPP0IW3XeeApZsCIDwo
135+x+YyxXQWJlf9L5TNYPRo+KFEdk3Cew0lv6QNs+xe
136 -----END RSA PRIVATE KEY-----
137
138=== modified file 'server/acceptance/suites/broadcast.go'
139--- server/acceptance/suites/broadcast.go 2014-08-15 09:33:48 +0000
140+++ server/acceptance/suites/broadcast.go 2014-09-04 19:21:18 +0000
141@@ -261,7 +261,7 @@
142 host, err := gh.Get()
143 c.Assert(err, IsNil)
144 expected := &gethosts.Host{
145- Domain: "localhost",
146+ Domain: "push-delivery",
147 Hosts: []string{s.ServerAddr},
148 }
149 c.Check(host, DeepEquals, expected)
150
151=== modified file 'server/acceptance/suites/suite.go'
152--- server/acceptance/suites/suite.go 2014-08-27 21:19:51 +0000
153+++ server/acceptance/suites/suite.go 2014-09-04 19:21:18 +0000
154@@ -111,7 +111,7 @@
155 }
156
157 func testClientSession(addr string, deviceId, model, imageChannel string, reportPings bool) *acceptance.ClientSession {
158- tlsConfig, err := kit.MakeTLSConfig("", false, helpers.SourceRelative("../ssl/testing.cert"), "")
159+ tlsConfig, err := kit.MakeTLSConfig("push-delivery", false, helpers.SourceRelative("../ssl/testing.cert"), "")
160 if err != nil {
161 panic(fmt.Sprintf("could not read ssl/testing.cert: %v", err))
162 }
163
164=== modified file 'server/config_test.go'
165--- server/config_test.go 2014-02-10 23:19:08 +0000
166+++ server/config_test.go 2014-09-04 19:21:18 +0000
167@@ -26,6 +26,7 @@
168 . "launchpad.net/gocheck"
169
170 "launchpad.net/ubuntu-push/config"
171+ helpers "launchpad.net/ubuntu-push/testing"
172 )
173
174 type configSuite struct{}
175@@ -52,22 +53,22 @@
176 c.Check(cfg.Addr(), Equals, "127.0.0.1:9999")
177 }
178
179-func (s *configSuite) TestDevicesParsedConfigLoadFinish(c *C) {
180+func (s *configSuite) TestTLSParsedConfigLoadPEMs(c *C) {
181 tmpDir := c.MkDir()
182- cfg := &DevicesParsedConfig{
183+ cfg := &TLSParsedConfig{
184 ParsedKeyPEMFile: "key.key",
185 ParsedCertPEMFile: "cert.cert",
186 }
187- err := cfg.FinishLoad(tmpDir)
188+ err := cfg.LoadPEMs(tmpDir)
189 c.Check(err, ErrorMatches, "reading key_pem_file:.*no such file.*")
190- err = ioutil.WriteFile(filepath.Join(tmpDir, "key.key"), []byte("KeY"), os.ModePerm)
191+ err = ioutil.WriteFile(filepath.Join(tmpDir, "key.key"), helpers.TestKeyPEMBlock, os.ModePerm)
192 c.Assert(err, IsNil)
193- err = cfg.FinishLoad(tmpDir)
194+ err = cfg.LoadPEMs(tmpDir)
195 c.Check(err, ErrorMatches, "reading cert_pem_file:.*no such file.*")
196- err = ioutil.WriteFile(filepath.Join(tmpDir, "cert.cert"), []byte("CeRt"), os.ModePerm)
197- c.Assert(err, IsNil)
198- err = cfg.FinishLoad(tmpDir)
199- c.Assert(err, IsNil)
200- c.Check(string(cfg.KeyPEMBlock()), Equals, "KeY")
201- c.Check(string(cfg.CertPEMBlock()), Equals, "CeRt")
202+ err = ioutil.WriteFile(filepath.Join(tmpDir, "cert.cert"), helpers.TestCertPEMBlock, os.ModePerm)
203+ c.Assert(err, IsNil)
204+ err = cfg.LoadPEMs(tmpDir)
205+ c.Assert(err, IsNil)
206+ tlsCfg := cfg.TLSServerConfig()
207+ c.Check(tlsCfg.Certificates, HasLen, 1)
208 }
209
210=== modified file 'server/dev/server.go'
211--- server/dev/server.go 2014-07-08 15:08:52 +0000
212+++ server/dev/server.go 2014-09-04 19:21:18 +0000
213@@ -64,7 +64,7 @@
214 if err != nil {
215 server.BootLogFatalf("reading config: %v", err)
216 }
217- err = cfg.DevicesParsedConfig.FinishLoad(filepath.Dir(cfgFpaths[len(cfgFpaths)-1]))
218+ err = cfg.DevicesParsedConfig.LoadPEMs(filepath.Dir(cfgFpaths[len(cfgFpaths)-1]))
219 if err != nil {
220 server.BootLogFatalf("reading config: %v", err)
221 }
222@@ -95,7 +95,7 @@
223 })
224 })
225 handler := api.PanicTo500Handler(mux, logger)
226- go server.HTTPServeRunner(nil, handler, &cfg.HTTPServeParsedConfig)()
227+ go server.HTTPServeRunner(nil, handler, &cfg.HTTPServeParsedConfig, nil)()
228 // listen for device connections
229 server.DevicesRunner(lst, func(conn net.Conn) error {
230 track := session.NewTracker(logger)
231
232=== modified file 'server/listener/listener.go'
233--- server/listener/listener.go 2014-03-06 19:21:44 +0000
234+++ server/listener/listener.go 2014-09-04 19:21:18 +0000
235@@ -30,10 +30,8 @@
236 type DeviceListenerConfig interface {
237 // Addr to listen on.
238 Addr() string
239- // TLS key
240- KeyPEMBlock() []byte
241- // TLS cert
242- CertPEMBlock() []byte
243+ // TLS config
244+ TLSServerConfig() *tls.Config
245 }
246
247 // DeviceListener listens and setup sessions from device connections.
248@@ -52,15 +50,8 @@
249 return nil, err
250 }
251 }
252- cert, err := tls.X509KeyPair(cfg.CertPEMBlock(), cfg.KeyPEMBlock())
253- if err != nil {
254- return nil, err
255- }
256- tlsCfg := &tls.Config{
257- Certificates: []tls.Certificate{cert},
258- SessionTicketsDisabled: true,
259- }
260- return &DeviceListener{tls.NewListener(lst, tlsCfg)}, err
261+ tlsCfg := cfg.TLSServerConfig()
262+ return &DeviceListener{tls.NewListener(lst, tlsCfg)}, nil
263 }
264
265 // handleTemporary checks and handles if the error is just a temporary network
266
267=== modified file 'server/listener/listener_test.go'
268--- server/listener/listener_test.go 2014-08-04 14:47:00 +0000
269+++ server/listener/listener_test.go 2014-09-04 19:21:18 +0000
270@@ -18,7 +18,6 @@
271
272 import (
273 "crypto/tls"
274- "crypto/x509"
275 "net"
276 "os/exec"
277 "regexp"
278@@ -68,12 +67,8 @@
279 return cfg.addr
280 }
281
282-func (cfg *testDevListenerCfg) KeyPEMBlock() []byte {
283- return helpers.TestKeyPEMBlock
284-}
285-
286-func (cfg *testDevListenerCfg) CertPEMBlock() []byte {
287- return helpers.TestCertPEMBlock
288+func (cfg *testDevListenerCfg) TLSServerConfig() *tls.Config {
289+ return helpers.TestTLSServerConfig
290 }
291
292 func (s *listenerSuite) TestDeviceListen(c *C) {
293@@ -130,11 +125,8 @@
294 return err
295 }
296
297-func testTlsDial(c *C, addr string) (net.Conn, error) {
298- cp := x509.NewCertPool()
299- ok := cp.AppendCertsFromPEM((&testDevListenerCfg{}).CertPEMBlock())
300- c.Assert(ok, Equals, true)
301- return tls.Dial("tcp", addr, &tls.Config{RootCAs: cp})
302+func testTlsDial(addr string) (net.Conn, error) {
303+ return tls.Dial("tcp", addr, helpers.TestTLSClientConfig)
304 }
305
306 func testWriteByte(c *C, conn net.Conn, toWrite uint32) {
307@@ -159,11 +151,11 @@
308 errCh <- lst.AcceptLoop(testSession, s.testlog)
309 }()
310 listenerAddr := lst.Addr().String()
311- conn1, err := testTlsDial(c, listenerAddr)
312+ conn1, err := testTlsDial(listenerAddr)
313 c.Assert(err, IsNil)
314 defer conn1.Close()
315 testWriteByte(c, conn1, '1')
316- conn2, err := testTlsDial(c, listenerAddr)
317+ conn2, err := testTlsDial(listenerAddr)
318 c.Assert(err, IsNil)
319 defer conn2.Close()
320 testWriteByte(c, conn2, '2')
321@@ -203,7 +195,7 @@
322 res, err := cmd.Output()
323 c.Assert(err, IsNil)
324 c.Assert(string(res), Matches, "(?s).*timed out.*")
325- conn2, err := testTlsDial(c, listenerAddr)
326+ conn2, err := testTlsDial(listenerAddr)
327 c.Assert(err, IsNil)
328 defer conn2.Close()
329 testWriteByte(c, conn2, '2')
330@@ -225,7 +217,7 @@
331 }, s.testlog)
332 }()
333 listenerAddr := lst.Addr().String()
334- _, err = testTlsDial(c, listenerAddr)
335+ _, err = testTlsDial(listenerAddr)
336 c.Assert(err, Not(IsNil))
337 lst.Close()
338 c.Check(<-errCh, ErrorMatches, ".*use of closed.*")
339@@ -244,7 +236,7 @@
340 }()
341 listenerAddr := lst.Addr().String()
342 c.Check(listenerAddr, Equals, foreignLst.Addr().String())
343- conn1, err := testTlsDial(c, listenerAddr)
344+ conn1, err := testTlsDial(listenerAddr)
345 c.Assert(err, IsNil)
346 defer conn1.Close()
347 testWriteByte(c, conn1, '1')
348
349=== modified file 'server/runner_devices.go'
350--- server/runner_devices.go 2014-03-12 12:34:18 +0000
351+++ server/runner_devices.go 2014-09-04 19:21:18 +0000
352@@ -17,7 +17,6 @@
353 package server
354
355 import (
356- "fmt"
357 "net"
358 "syscall"
359 "time"
360@@ -36,26 +35,8 @@
361 ParsedSessionQueueSize config.ConfigQueueSize `json:"session_queue_size"`
362 ParsedBrokerQueueSize config.ConfigQueueSize `json:"broker_queue_size"`
363 // device listener configuration
364- ParsedAddr config.ConfigHostPort `json:"addr"`
365- ParsedKeyPEMFile string `json:"key_pem_file"`
366- ParsedCertPEMFile string `json:"cert_pem_file"`
367- // private post-processed config
368- certPEMBlock []byte
369- keyPEMBlock []byte
370-}
371-
372-func (cfg *DevicesParsedConfig) FinishLoad(baseDir string) error {
373- keyPEMBlock, err := config.LoadFile(cfg.ParsedKeyPEMFile, baseDir)
374- if err != nil {
375- return fmt.Errorf("reading key_pem_file: %v", err)
376- }
377- certPEMBlock, err := config.LoadFile(cfg.ParsedCertPEMFile, baseDir)
378- if err != nil {
379- return fmt.Errorf("reading cert_pem_file: %v", err)
380- }
381- cfg.keyPEMBlock = keyPEMBlock
382- cfg.certPEMBlock = certPEMBlock
383- return nil
384+ ParsedAddr config.ConfigHostPort `json:"addr"`
385+ TLSParsedConfig
386 }
387
388 func (cfg *DevicesParsedConfig) PingInterval() time.Duration {
389@@ -78,14 +59,6 @@
390 return cfg.ParsedAddr.HostPort()
391 }
392
393-func (cfg *DevicesParsedConfig) KeyPEMBlock() []byte {
394- return cfg.keyPEMBlock
395-}
396-
397-func (cfg *DevicesParsedConfig) CertPEMBlock() []byte {
398- return cfg.certPEMBlock
399-}
400-
401 // DevicesRunner returns a function to accept device connections.
402 // If adoptLst is not nil it will be used as the underlying listener, instead
403 // of creating one, wrapped in a TLS layer.
404
405=== modified file 'server/runner_http.go'
406--- server/runner_http.go 2014-03-25 19:02:18 +0000
407+++ server/runner_http.go 2014-09-04 19:21:18 +0000
408@@ -17,6 +17,7 @@
409 package server
410
411 import (
412+ "crypto/tls"
413 "net"
414 "net/http"
415
416@@ -32,7 +33,8 @@
417
418 // HTTPServeRunner returns a function to serve HTTP requests.
419 // If httpLst is not nil it will be used as the underlying listener.
420-func HTTPServeRunner(httpLst net.Listener, h http.Handler, parsedCfg *HTTPServeParsedConfig) func() {
421+// If tlsCfg is not nit server over TLS with the config.
422+func HTTPServeRunner(httpLst net.Listener, h http.Handler, parsedCfg *HTTPServeParsedConfig, tlsCfg *tls.Config) func() {
423 if httpLst == nil {
424 var err error
425 httpLst, err = net.Listen("tcp", parsedCfg.ParsedHTTPAddr.HostPort())
426@@ -46,6 +48,9 @@
427 ReadTimeout: parsedCfg.ParsedHTTPReadTimeout.TimeDuration(),
428 WriteTimeout: parsedCfg.ParsedHTTPWriteTimeout.TimeDuration(),
429 }
430+ if tlsCfg != nil {
431+ httpLst = tls.NewListener(httpLst, tlsCfg)
432+ }
433 return func() {
434 err := srv.Serve(httpLst)
435 if err != nil {
436
437=== modified file 'server/runner_test.go'
438--- server/runner_test.go 2014-03-25 19:02:18 +0000
439+++ server/runner_test.go 2014-09-04 19:21:18 +0000
440@@ -17,6 +17,7 @@
441 package server
442
443 import (
444+ "crypto/tls"
445 "fmt"
446 "io/ioutil"
447 "net"
448@@ -68,7 +69,7 @@
449 func (s *runnerSuite) TestHTTPServeRunner(c *C) {
450 errCh := make(chan interface{}, 1)
451 h := http.HandlerFunc(testHandle)
452- runner := HTTPServeRunner(nil, h, &testHTTPServeParsedConfig)
453+ runner := HTTPServeRunner(nil, h, &testHTTPServeParsedConfig, nil)
454 c.Assert(s.lst, Not(IsNil))
455 defer s.lst.Close()
456 c.Check(s.kind, Equals, "http")
457@@ -89,16 +90,25 @@
458 c.Check(<-errCh, Matches, "accepting http connections:.*closed.*")
459 }
460
461+func cert() tls.Certificate {
462+ cert, err := tls.X509KeyPair(helpers.TestCertPEMBlock, helpers.TestKeyPEMBlock)
463+ if err != nil {
464+ panic(err)
465+ }
466+ return cert
467+}
468+
469 var testDevicesParsedConfig = DevicesParsedConfig{
470 ParsedPingInterval: config.ConfigTimeDuration{60 * time.Second},
471 ParsedExchangeTimeout: config.ConfigTimeDuration{10 * time.Second},
472 ParsedBrokerQueueSize: config.ConfigQueueSize(1000),
473 ParsedSessionQueueSize: config.ConfigQueueSize(10),
474 ParsedAddr: "127.0.0.1:0",
475- ParsedKeyPEMFile: "",
476- ParsedCertPEMFile: "",
477- keyPEMBlock: helpers.TestKeyPEMBlock,
478- certPEMBlock: helpers.TestCertPEMBlock,
479+ TLSParsedConfig: TLSParsedConfig{
480+ ParsedKeyPEMFile: "",
481+ ParsedCertPEMFile: "",
482+ cert: cert(),
483+ },
484 }
485
486 func (s *runnerSuite) TestDevicesRunner(c *C) {
487@@ -135,7 +145,36 @@
488 lst0, err := net.Listen("tcp", "127.0.0.1:0")
489 c.Assert(err, IsNil)
490 defer lst0.Close()
491- HTTPServeRunner(lst0, nil, &testHTTPServeParsedConfig)
492+ HTTPServeRunner(lst0, nil, &testHTTPServeParsedConfig, nil)
493 c.Assert(s.lst, Equals, lst0)
494 c.Check(s.kind, Equals, "http")
495 }
496+
497+func (s *runnerSuite) TestHTTPServeRunnerTLS(c *C) {
498+ errCh := make(chan interface{}, 1)
499+ h := http.HandlerFunc(testHandle)
500+ runner := HTTPServeRunner(nil, h, &testHTTPServeParsedConfig, helpers.TestTLSServerConfig)
501+ c.Assert(s.lst, Not(IsNil))
502+ defer s.lst.Close()
503+ c.Check(s.kind, Equals, "http")
504+ go func() {
505+ defer func() {
506+ errCh <- recover()
507+ }()
508+ runner()
509+ }()
510+ cli := http.Client{
511+ Transport: &http.Transport{
512+ TLSClientConfig: helpers.TestTLSClientConfig,
513+ },
514+ }
515+ resp, err := cli.Get(fmt.Sprintf("https://%s/", s.lst.Addr()))
516+ c.Assert(err, IsNil)
517+ defer resp.Body.Close()
518+ c.Assert(resp.StatusCode, Equals, 200)
519+ body, err := ioutil.ReadAll(resp.Body)
520+ c.Assert(err, IsNil)
521+ c.Check(string(body), Equals, "yay!\n")
522+ s.lst.Close()
523+ c.Check(<-errCh, Matches, "accepting http connections:.*closed.*")
524+}
525
526=== added file 'server/tlsconfig.go'
527--- server/tlsconfig.go 1970-01-01 00:00:00 +0000
528+++ server/tlsconfig.go 2014-09-04 19:21:18 +0000
529@@ -0,0 +1,53 @@
530+/*
531+ Copyright 2013-2014 Canonical Ltd.
532+
533+ This program is free software: you can redistribute it and/or modify it
534+ under the terms of the GNU General Public License version 3, as published
535+ by the Free Software Foundation.
536+
537+ This program is distributed in the hope that it will be useful, but
538+ WITHOUT ANY WARRANTY; without even the implied warranties of
539+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
540+ PURPOSE. See the GNU General Public License for more details.
541+
542+ You should have received a copy of the GNU General Public License along
543+ with this program. If not, see <http://www.gnu.org/licenses/>.
544+*/
545+
546+package server
547+
548+import (
549+ "crypto/tls"
550+ "fmt"
551+
552+ "launchpad.net/ubuntu-push/config"
553+)
554+
555+// A TLSParsedConfig holds and can be used to parse a tls server config.
556+type TLSParsedConfig struct {
557+ ParsedKeyPEMFile string `json:"key_pem_file"`
558+ ParsedCertPEMFile string `json:"cert_pem_file"`
559+ // private post-processed config
560+ cert tls.Certificate
561+}
562+
563+func (cfg *TLSParsedConfig) LoadPEMs(baseDir string) error {
564+ keyPEMBlock, err := config.LoadFile(cfg.ParsedKeyPEMFile, baseDir)
565+ if err != nil {
566+ return fmt.Errorf("reading key_pem_file: %v", err)
567+ }
568+ certPEMBlock, err := config.LoadFile(cfg.ParsedCertPEMFile, baseDir)
569+ if err != nil {
570+ return fmt.Errorf("reading cert_pem_file: %v", err)
571+ }
572+ cfg.cert, err = tls.X509KeyPair(certPEMBlock, keyPEMBlock)
573+ return err
574+}
575+
576+func (cfg *TLSParsedConfig) TLSServerConfig() *tls.Config {
577+ tlsCfg := &tls.Config{
578+ Certificates: []tls.Certificate{cfg.cert},
579+ SessionTicketsDisabled: true,
580+ }
581+ return tlsCfg
582+}
583
584=== modified file 'testing/tls.go'
585--- testing/tls.go 2014-01-21 21:36:07 +0000
586+++ testing/tls.go 2014-09-04 19:21:18 +0000
587@@ -16,26 +16,53 @@
588
589 package testing
590
591-// key&cert generated with go run /usr/lib/go/src/pkg/crypto/tls/generate_cert.go -ca -host localhost -rsa-bits 512 -duration 87600h
592+import (
593+ "crypto/tls"
594+ "crypto/x509"
595+)
596+
597+// key&cert generated with go run /usr/lib/go/src/pkg/crypto/tls/generate_cert.go -ca -host push-delivery -rsa-bits 512 -duration 87600h
598 var (
599 TestKeyPEMBlock = []byte(`-----BEGIN RSA PRIVATE KEY-----
600-MIIBPAIBAAJBAPw+niki17X2qALE2A2AzE1q5dvK9CI4OduRtT9IgbFLC6psqAT2
601-1NA+QbY17nWSSpyP65zkMkwKXrbDzstwLPkCAwEAAQJAKwXbIBULScP6QA6m8xam
602-wgWbkvN41GVWqPafPV32kPBvKwSc+M1e+JR7g3/xPZE7TCELcfYi4yXEHZZI3Pbh
603-oQIhAP/UsgJbsfH1GFv8Y8qGl5l/kmwwkwHhuKvEC87Yur9FAiEA/GlQv3ZfaXnT
604-lcCFT0aL02O0RDiRYyMUG/JAZQJs6CUCIQCHO5SZYIUwxIGK5mCNxxXOAzyQSiD7
605-hqkKywf+4FvfDQIhALa0TLyqJFom0t7c4iIGAIRc8UlIYQSPiajI64+x9775AiEA
606-0v4fgSK/Rq059zW1753JjuB6aR0Uh+3RqJII4dUR1Wg=
607+MIIBOgIBAAJBANRU+pZKMNHpMvg549meJ060xQ4HCjrfVq+AeIER9W1pkaknDj8c
608+hwOWKHTeztcPF/LHVpKPabn+fSNbFlq+SzcCAwEAAQJBAIOO+4xu/3yv/rKqO7C0
609+Oyqa+pVMa1w60R0AfqmKFQTqiTgevM77uqjpW1+t0hpK20nyj6MUIPaL+9kZgp7t
610+mnECIQDqw79PXSzudf10XGy9ve5bRazINHxQYgJ7FvlTT6JhdQIhAOeJxq9zcKni
611+69ueO1ualz0hn8w6uHPsG9FlZ8C+7Jh7AiAWJgebjjfZ+4nA+6NKt2uQct9dOA5u
612+awC+6ij1ojK4rQIgNEqAbcWDj0qpe8sLms+aEntSjJxCZiPP0IW3XeeApZsCIDwo
613+x+YyxXQWJlf9L5TNYPRo+KFEdk3Cew0lv6QNs+xe
614 -----END RSA PRIVATE KEY-----`)
615
616 TestCertPEMBlock = []byte(`-----BEGIN CERTIFICATE-----
617 MIIBYzCCAQ+gAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
618-bzAeFw0xMzEyMTkyMDU1NDNaFw0yMzEyMTcyMDU1NDNaMBIxEDAOBgNVBAoTB0Fj
619-bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAPw+niki17X2qALE2A2AzE1q5dvK
620-9CI4OduRtT9IgbFLC6psqAT21NA+QbY17nWSSpyP65zkMkwKXrbDzstwLPkCAwEA
621-AaNUMFIwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
622-EwEB/wQFMAMBAf8wGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMAsGCSqGSIb3
623-DQEBBQNBAFqiVI+Km2XPSO+pxITaPvhmuzg+XG3l1+2di3gL+HlDobocjBqRctRU
624-YySO32W07acjGJmCHUKpCJuq9X8hpmk=
625+bzAeFw0xNDA4MjkxMjQyMDFaFw0yNDA4MjYxMjQyMDFaMBIxEDAOBgNVBAoTB0Fj
626+bWUgQ28wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA1FT6lkow0eky+Dnj2Z4nTrTF
627+DgcKOt9Wr4B4gRH1bWmRqScOPxyHA5YodN7O1w8X8sdWko9puf59I1sWWr5LNwID
628+AQABo1IwUDAOBgNVHQ8BAf8EBAMCAKQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYD
629+VR0TAQH/BAUwAwEB/zAYBgNVHREEETAPgg1wdXNoLWRlbGl2ZXJ5MAsGCSqGSIb3
630+DQEBBQNBABtWCdMFkhIO8+oM3vugOWle9WJZ1FCRWD+cMl76mI1lhmNF4lvEZG47
631+xUjekA1+heU39WpOEzZSybrOdiEaGbI=
632 -----END CERTIFICATE-----`)
633 )
634+
635+// test tls server & client config
636+var TestTLSServerConfig, TestTLSClientConfig *tls.Config
637+
638+func init() {
639+ cert, err := tls.X509KeyPair(TestCertPEMBlock, TestKeyPEMBlock)
640+ if err != nil {
641+ panic(err)
642+ }
643+ TestTLSServerConfig = &tls.Config{
644+ Certificates: []tls.Certificate{cert},
645+ }
646+ cp := x509.NewCertPool()
647+ ok := cp.AppendCertsFromPEM(TestCertPEMBlock)
648+ if !ok {
649+ panic("failed to parse test cert")
650+ }
651+ TestTLSClientConfig = &tls.Config{
652+ RootCAs: cp,
653+ ServerName: "push-delivery",
654+ }
655+}

Subscribers

People subscribed via source and target branches