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

Proposed by Samuele Pedroni
Status: Superseded
Proposed branch: lp:~pedronis/ubuntu-push/http-ssl
Merge into: lp:ubuntu-push
Diff against target: 864 lines (+252/-206)
20 files modified
client/session/session_test.go (+4/-25)
debian/ubuntu-push-client.conf (+4/-0)
docs/highlevel.txt (+25/-34)
docs/lowlevel.txt (+25/-34)
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
Ubuntu Push Hackers Pending
Review via email: mp+233402@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

Unmerged revisions

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 17:51:30 +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 'debian/ubuntu-push-client.conf'
60--- debian/ubuntu-push-client.conf 2014-08-06 14:08:29 +0000
61+++ debian/ubuntu-push-client.conf 2014-09-04 17:51:30 +0000
62@@ -3,6 +3,10 @@
63 start on started unity8
64 stop on stopping unity8
65
66+# set the media role for sounds to notifications' role
67+env PULSE_PROP="media.role=alert"
68+export PULSE_PROP
69+
70 exec /usr/lib/ubuntu-push-client/ubuntu-push-client
71 respawn
72
73
74=== modified file 'docs/highlevel.txt'
75--- docs/highlevel.txt 2014-08-08 09:09:39 +0000
76+++ docs/highlevel.txt 2014-09-04 17:51:30 +0000
77@@ -3,6 +3,8 @@
78
79 :Version: 0.50+
80
81+.. contents::
82+
83 Introduction
84 ------------
85
86@@ -111,8 +113,8 @@
87 Persistent Notification Management
88 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
89
90-Some notifications are persistent, meaning they don't disappear automatically. For those notifications, there is an API that
91-allows the app to manage them without having to know the underlying details of the platform.
92+Some notifications are persistent, meaning that, after they are presented, they don't disappear automatically.
93+This API allows the app to manage that type of notifications.
94
95 On each notification there's an optional ``tag`` field, used for this purpose.
96
97@@ -192,6 +194,8 @@
98
99 Helpers output has two parts, the postal message (in the "message" key) and a notification to be presented to the user (in the "notification" key).
100
101+.. note:: This format **will** change with future versions of the SDK and it **may** be incompatible.
102+
103 Here's a simple example::
104
105 {
106@@ -281,37 +285,27 @@
107 The Ubuntu Push server is located at https://push.ubuntu.com and has a single endpoint: ``/notify``.
108 To notify a user, your application has to do a POST with ``Content-type: application/json``.
109
110+.. note:: The contents of the data field are arbitrary. They should be enough for your helper to build
111+ a notification using it, and decide whether it should be displayed or not. Keep in mind
112+ that this will be processed by more than one version of the helper, because the user may be using
113+ an older version of your app.
114+
115 Here is an example of the POST body using all the fields::
116
117- {
118- "appid": "com.ubuntu.music_music",
119- "expire_on": "2014-10-08T14:48:00.000Z",
120- "token": "LeA4tRQG9hhEkuhngdouoA==",
121- "clear_pending": true,
122- "replace_tag": "tagname",
123- "data": {
124- "message": "foobar",
125- "notification": {
126- "card": {
127- "summary": "yes",
128- "body": "hello",
129- "popup": true,
130- "persist": true,
131- "timestamp": 1407160197
132- }
133- "sound": "buzz.mp3",
134- "tag": "foo",
135- "vibrate": {
136- "pattern": [200, 100],
137- "repeat": 2
138- }
139- "emblem-counter": {
140- "count": 12,
141- "visible": true
142- }
143- }
144- }
145- }
146+ {
147+ "appid": "com.ubuntu.music_music",
148+ "expire_on": "2014-10-08T14:48:00.000Z",
149+ "token": "LeA4tRQG9hhEkuhngdouoA==",
150+ "clear_pending": true,
151+ "replace_tag": "tagname",
152+ "data": {
153+ "id": 43578,
154+ "timestamp": 1409583746,
155+ "serial": 1254,
156+ "sender": "Joe",
157+ "snippet": "Hi there!"
158+ }
159+ }
160
161
162 :appid: ID of the application that will receive the notification, as described in the client side documentation.
163@@ -320,6 +314,3 @@
164 :clear_pending: Discards all previous pending notifications. Usually in response to getting a "too-many-pending" error.
165 :replace_tag: If there's a pending notification with the same tag, delete it before queuing this new one.
166 :data: A JSON object.
167-
168-In this example, data is `what a helper would output <#helper-output-format>`__ but that's not necessarily the case.
169-The content of the data field will be passed to the helper application which **has** to produce output in that format.
170
171=== modified file 'docs/lowlevel.txt'
172--- docs/lowlevel.txt 2014-08-08 09:09:39 +0000
173+++ docs/lowlevel.txt 2014-09-04 17:51:30 +0000
174@@ -3,6 +3,8 @@
175
176 :Version: 0.50+
177
178+.. contents::
179+
180 Introduction
181 ------------
182
183@@ -202,8 +204,8 @@
184 Persistent Notification Management
185 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
186
187-Some notifications are persistent, meaning they don't disappear automatically. For those notifications, there is an API that
188-allows the app to manage them without having to know the underlying details of the platform.
189+Some notifications are persistent, meaning that, after they are presented, they don't disappear automatically.
190+This API allows the app to manage that type of notifications.
191
192 On each notification there's an optional ``tag`` field, used for this purpose.
193
194@@ -286,6 +288,8 @@
195
196 Helpers output has two parts, the postal message (in the "message" key) and a notification to be presented to the user (in the "notification" key).
197
198+.. note:: This format **will** change with future versions of the SDK and it **may** be incompatible.
199+
200 Here's a simple example::
201
202 {
203@@ -375,37 +379,27 @@
204 The Ubuntu Push server is located at https://push.ubuntu.com and has a single endpoint: ``/notify``.
205 To notify a user, your application has to do a POST with ``Content-type: application/json``.
206
207+.. note:: The contents of the data field are arbitrary. They should be enough for your helper to build
208+ a notification using it, and decide whether it should be displayed or not. Keep in mind
209+ that this will be processed by more than one version of the helper, because the user may be using
210+ an older version of your app.
211+
212 Here is an example of the POST body using all the fields::
213
214- {
215- "appid": "com.ubuntu.music_music",
216- "expire_on": "2014-10-08T14:48:00.000Z",
217- "token": "LeA4tRQG9hhEkuhngdouoA==",
218- "clear_pending": true,
219- "replace_tag": "tagname",
220- "data": {
221- "message": "foobar",
222- "notification": {
223- "card": {
224- "summary": "yes",
225- "body": "hello",
226- "popup": true,
227- "persist": true,
228- "timestamp": 1407160197
229- }
230- "sound": "buzz.mp3",
231- "tag": "foo",
232- "vibrate": {
233- "pattern": [200, 100],
234- "repeat": 2
235- }
236- "emblem-counter": {
237- "count": 12,
238- "visible": true
239- }
240- }
241- }
242- }
243+ {
244+ "appid": "com.ubuntu.music_music",
245+ "expire_on": "2014-10-08T14:48:00.000Z",
246+ "token": "LeA4tRQG9hhEkuhngdouoA==",
247+ "clear_pending": true,
248+ "replace_tag": "tagname",
249+ "data": {
250+ "id": 43578,
251+ "timestamp": 1409583746,
252+ "serial": 1254,
253+ "sender": "Joe",
254+ "snippet": "Hi there!"
255+ }
256+ }
257
258
259 :appid: ID of the application that will receive the notification, as described in the client side documentation.
260@@ -414,6 +408,3 @@
261 :clear_pending: Discards all previous pending notifications. Usually in response to getting a "too-many-pending" error.
262 :replace_tag: If there's a pending notification with the same tag, delete it before queuing this new one.
263 :data: A JSON object.
264-
265-In this example, data is `what a helper would output <#helper-output-format>`__ but that's not necessarily the case.
266-The content of the data field will be passed to the helper application which **has** to produce output in that format.
267
268=== modified file 'sampleconfigs/dev.json'
269--- sampleconfigs/dev.json 2014-07-15 17:14:07 +0000
270+++ sampleconfigs/dev.json 2014-09-04 17:51:30 +0000
271@@ -10,5 +10,5 @@
272 "http_read_timeout": "5s",
273 "http_write_timeout": "5s",
274 "max_notifications_per_app": 25,
275- "delivery_domain": "localhost"
276+ "delivery_domain": "pus-delivery"
277 }
278
279=== modified file 'server/acceptance/acceptance_test.go'
280--- server/acceptance/acceptance_test.go 2014-05-02 09:56:49 +0000
281+++ server/acceptance/acceptance_test.go 2014-09-04 17:51:30 +0000
282@@ -34,7 +34,7 @@
283 cfg := make(map[string]interface{})
284 suites.FillServerConfig(cfg, addr)
285 suites.FillHTTPServerConfig(cfg, httpAddr)
286- cfg["delivery_domain"] = "localhost"
287+ cfg["delivery_domain"] = "push-delivery"
288 return cfg
289 }
290
291
292=== modified file 'server/acceptance/ssl/README'
293--- server/acceptance/ssl/README 2014-02-21 16:17:28 +0000
294+++ server/acceptance/ssl/README 2014-09-04 17:51:30 +0000
295@@ -3,6 +3,6 @@
296
297 Generated with:
298
299- go run /usr/lib/go/src/pkg/crypto/tls/generate_cert.go -ca -host localhost -rsa-bits 512 -duration 87600h
300+ go run /usr/lib/go/src/pkg/crypto/tls/generate_cert.go -ca -host push-delivery -rsa-bits 512 -duration 87600h
301
302 and then renamed.
303
304=== modified file 'server/acceptance/ssl/testing.cert'
305--- server/acceptance/ssl/testing.cert 2014-01-14 15:35:20 +0000
306+++ server/acceptance/ssl/testing.cert 2014-09-04 17:51:30 +0000
307@@ -1,10 +1,10 @@
308 -----BEGIN CERTIFICATE-----
309 MIIBYzCCAQ+gAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
310-bzAeFw0xMzEyMTkyMDU1NDNaFw0yMzEyMTcyMDU1NDNaMBIxEDAOBgNVBAoTB0Fj
311-bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAPw+niki17X2qALE2A2AzE1q5dvK
312-9CI4OduRtT9IgbFLC6psqAT21NA+QbY17nWSSpyP65zkMkwKXrbDzstwLPkCAwEA
313-AaNUMFIwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
314-EwEB/wQFMAMBAf8wGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMAsGCSqGSIb3
315-DQEBBQNBAFqiVI+Km2XPSO+pxITaPvhmuzg+XG3l1+2di3gL+HlDobocjBqRctRU
316-YySO32W07acjGJmCHUKpCJuq9X8hpmk=
317+bzAeFw0xNDA4MjkxMjQyMDFaFw0yNDA4MjYxMjQyMDFaMBIxEDAOBgNVBAoTB0Fj
318+bWUgQ28wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA1FT6lkow0eky+Dnj2Z4nTrTF
319+DgcKOt9Wr4B4gRH1bWmRqScOPxyHA5YodN7O1w8X8sdWko9puf59I1sWWr5LNwID
320+AQABo1IwUDAOBgNVHQ8BAf8EBAMCAKQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYD
321+VR0TAQH/BAUwAwEB/zAYBgNVHREEETAPgg1wdXNoLWRlbGl2ZXJ5MAsGCSqGSIb3
322+DQEBBQNBABtWCdMFkhIO8+oM3vugOWle9WJZ1FCRWD+cMl76mI1lhmNF4lvEZG47
323+xUjekA1+heU39WpOEzZSybrOdiEaGbI=
324 -----END CERTIFICATE-----
325
326=== modified file 'server/acceptance/ssl/testing.key'
327--- server/acceptance/ssl/testing.key 2014-01-14 15:35:20 +0000
328+++ server/acceptance/ssl/testing.key 2014-09-04 17:51:30 +0000
329@@ -1,9 +1,9 @@
330 -----BEGIN RSA PRIVATE KEY-----
331-MIIBPAIBAAJBAPw+niki17X2qALE2A2AzE1q5dvK9CI4OduRtT9IgbFLC6psqAT2
332-1NA+QbY17nWSSpyP65zkMkwKXrbDzstwLPkCAwEAAQJAKwXbIBULScP6QA6m8xam
333-wgWbkvN41GVWqPafPV32kPBvKwSc+M1e+JR7g3/xPZE7TCELcfYi4yXEHZZI3Pbh
334-oQIhAP/UsgJbsfH1GFv8Y8qGl5l/kmwwkwHhuKvEC87Yur9FAiEA/GlQv3ZfaXnT
335-lcCFT0aL02O0RDiRYyMUG/JAZQJs6CUCIQCHO5SZYIUwxIGK5mCNxxXOAzyQSiD7
336-hqkKywf+4FvfDQIhALa0TLyqJFom0t7c4iIGAIRc8UlIYQSPiajI64+x9775AiEA
337-0v4fgSK/Rq059zW1753JjuB6aR0Uh+3RqJII4dUR1Wg=
338+MIIBOgIBAAJBANRU+pZKMNHpMvg549meJ060xQ4HCjrfVq+AeIER9W1pkaknDj8c
339+hwOWKHTeztcPF/LHVpKPabn+fSNbFlq+SzcCAwEAAQJBAIOO+4xu/3yv/rKqO7C0
340+Oyqa+pVMa1w60R0AfqmKFQTqiTgevM77uqjpW1+t0hpK20nyj6MUIPaL+9kZgp7t
341+mnECIQDqw79PXSzudf10XGy9ve5bRazINHxQYgJ7FvlTT6JhdQIhAOeJxq9zcKni
342+69ueO1ualz0hn8w6uHPsG9FlZ8C+7Jh7AiAWJgebjjfZ+4nA+6NKt2uQct9dOA5u
343+awC+6ij1ojK4rQIgNEqAbcWDj0qpe8sLms+aEntSjJxCZiPP0IW3XeeApZsCIDwo
344+x+YyxXQWJlf9L5TNYPRo+KFEdk3Cew0lv6QNs+xe
345 -----END RSA PRIVATE KEY-----
346
347=== modified file 'server/acceptance/suites/broadcast.go'
348--- server/acceptance/suites/broadcast.go 2014-08-15 09:33:48 +0000
349+++ server/acceptance/suites/broadcast.go 2014-09-04 17:51:30 +0000
350@@ -261,7 +261,7 @@
351 host, err := gh.Get()
352 c.Assert(err, IsNil)
353 expected := &gethosts.Host{
354- Domain: "localhost",
355+ Domain: "push-delivery",
356 Hosts: []string{s.ServerAddr},
357 }
358 c.Check(host, DeepEquals, expected)
359
360=== modified file 'server/acceptance/suites/suite.go'
361--- server/acceptance/suites/suite.go 2014-08-27 21:19:51 +0000
362+++ server/acceptance/suites/suite.go 2014-09-04 17:51:30 +0000
363@@ -111,7 +111,7 @@
364 }
365
366 func testClientSession(addr string, deviceId, model, imageChannel string, reportPings bool) *acceptance.ClientSession {
367- tlsConfig, err := kit.MakeTLSConfig("", false, helpers.SourceRelative("../ssl/testing.cert"), "")
368+ tlsConfig, err := kit.MakeTLSConfig("push-delivery", false, helpers.SourceRelative("../ssl/testing.cert"), "")
369 if err != nil {
370 panic(fmt.Sprintf("could not read ssl/testing.cert: %v", err))
371 }
372
373=== modified file 'server/config_test.go'
374--- server/config_test.go 2014-02-10 23:19:08 +0000
375+++ server/config_test.go 2014-09-04 17:51:30 +0000
376@@ -26,6 +26,7 @@
377 . "launchpad.net/gocheck"
378
379 "launchpad.net/ubuntu-push/config"
380+ helpers "launchpad.net/ubuntu-push/testing"
381 )
382
383 type configSuite struct{}
384@@ -52,22 +53,22 @@
385 c.Check(cfg.Addr(), Equals, "127.0.0.1:9999")
386 }
387
388-func (s *configSuite) TestDevicesParsedConfigLoadFinish(c *C) {
389+func (s *configSuite) TestTLSParsedConfigLoadPEMs(c *C) {
390 tmpDir := c.MkDir()
391- cfg := &DevicesParsedConfig{
392+ cfg := &TLSParsedConfig{
393 ParsedKeyPEMFile: "key.key",
394 ParsedCertPEMFile: "cert.cert",
395 }
396- err := cfg.FinishLoad(tmpDir)
397+ err := cfg.LoadPEMs(tmpDir)
398 c.Check(err, ErrorMatches, "reading key_pem_file:.*no such file.*")
399- err = ioutil.WriteFile(filepath.Join(tmpDir, "key.key"), []byte("KeY"), os.ModePerm)
400+ err = ioutil.WriteFile(filepath.Join(tmpDir, "key.key"), helpers.TestKeyPEMBlock, os.ModePerm)
401 c.Assert(err, IsNil)
402- err = cfg.FinishLoad(tmpDir)
403+ err = cfg.LoadPEMs(tmpDir)
404 c.Check(err, ErrorMatches, "reading cert_pem_file:.*no such file.*")
405- err = ioutil.WriteFile(filepath.Join(tmpDir, "cert.cert"), []byte("CeRt"), os.ModePerm)
406- c.Assert(err, IsNil)
407- err = cfg.FinishLoad(tmpDir)
408- c.Assert(err, IsNil)
409- c.Check(string(cfg.KeyPEMBlock()), Equals, "KeY")
410- c.Check(string(cfg.CertPEMBlock()), Equals, "CeRt")
411+ err = ioutil.WriteFile(filepath.Join(tmpDir, "cert.cert"), helpers.TestCertPEMBlock, os.ModePerm)
412+ c.Assert(err, IsNil)
413+ err = cfg.LoadPEMs(tmpDir)
414+ c.Assert(err, IsNil)
415+ tlsCfg := cfg.TLSServerConfig()
416+ c.Check(tlsCfg.Certificates, HasLen, 1)
417 }
418
419=== modified file 'server/dev/server.go'
420--- server/dev/server.go 2014-07-08 15:08:52 +0000
421+++ server/dev/server.go 2014-09-04 17:51:30 +0000
422@@ -64,7 +64,7 @@
423 if err != nil {
424 server.BootLogFatalf("reading config: %v", err)
425 }
426- err = cfg.DevicesParsedConfig.FinishLoad(filepath.Dir(cfgFpaths[len(cfgFpaths)-1]))
427+ err = cfg.DevicesParsedConfig.LoadPEMs(filepath.Dir(cfgFpaths[len(cfgFpaths)-1]))
428 if err != nil {
429 server.BootLogFatalf("reading config: %v", err)
430 }
431@@ -95,7 +95,7 @@
432 })
433 })
434 handler := api.PanicTo500Handler(mux, logger)
435- go server.HTTPServeRunner(nil, handler, &cfg.HTTPServeParsedConfig)()
436+ go server.HTTPServeRunner(nil, handler, &cfg.HTTPServeParsedConfig, nil)()
437 // listen for device connections
438 server.DevicesRunner(lst, func(conn net.Conn) error {
439 track := session.NewTracker(logger)
440
441=== modified file 'server/listener/listener.go'
442--- server/listener/listener.go 2014-03-06 19:21:44 +0000
443+++ server/listener/listener.go 2014-09-04 17:51:30 +0000
444@@ -30,10 +30,8 @@
445 type DeviceListenerConfig interface {
446 // Addr to listen on.
447 Addr() string
448- // TLS key
449- KeyPEMBlock() []byte
450- // TLS cert
451- CertPEMBlock() []byte
452+ // TLS config
453+ TLSServerConfig() *tls.Config
454 }
455
456 // DeviceListener listens and setup sessions from device connections.
457@@ -52,15 +50,8 @@
458 return nil, err
459 }
460 }
461- cert, err := tls.X509KeyPair(cfg.CertPEMBlock(), cfg.KeyPEMBlock())
462- if err != nil {
463- return nil, err
464- }
465- tlsCfg := &tls.Config{
466- Certificates: []tls.Certificate{cert},
467- SessionTicketsDisabled: true,
468- }
469- return &DeviceListener{tls.NewListener(lst, tlsCfg)}, err
470+ tlsCfg := cfg.TLSServerConfig()
471+ return &DeviceListener{tls.NewListener(lst, tlsCfg)}, nil
472 }
473
474 // handleTemporary checks and handles if the error is just a temporary network
475
476=== modified file 'server/listener/listener_test.go'
477--- server/listener/listener_test.go 2014-08-04 14:47:00 +0000
478+++ server/listener/listener_test.go 2014-09-04 17:51:30 +0000
479@@ -18,7 +18,6 @@
480
481 import (
482 "crypto/tls"
483- "crypto/x509"
484 "net"
485 "os/exec"
486 "regexp"
487@@ -68,12 +67,8 @@
488 return cfg.addr
489 }
490
491-func (cfg *testDevListenerCfg) KeyPEMBlock() []byte {
492- return helpers.TestKeyPEMBlock
493-}
494-
495-func (cfg *testDevListenerCfg) CertPEMBlock() []byte {
496- return helpers.TestCertPEMBlock
497+func (cfg *testDevListenerCfg) TLSServerConfig() *tls.Config {
498+ return helpers.TestTLSServerConfig
499 }
500
501 func (s *listenerSuite) TestDeviceListen(c *C) {
502@@ -130,11 +125,8 @@
503 return err
504 }
505
506-func testTlsDial(c *C, addr string) (net.Conn, error) {
507- cp := x509.NewCertPool()
508- ok := cp.AppendCertsFromPEM((&testDevListenerCfg{}).CertPEMBlock())
509- c.Assert(ok, Equals, true)
510- return tls.Dial("tcp", addr, &tls.Config{RootCAs: cp})
511+func testTlsDial(addr string) (net.Conn, error) {
512+ return tls.Dial("tcp", addr, helpers.TestTLSClientConfig)
513 }
514
515 func testWriteByte(c *C, conn net.Conn, toWrite uint32) {
516@@ -159,11 +151,11 @@
517 errCh <- lst.AcceptLoop(testSession, s.testlog)
518 }()
519 listenerAddr := lst.Addr().String()
520- conn1, err := testTlsDial(c, listenerAddr)
521+ conn1, err := testTlsDial(listenerAddr)
522 c.Assert(err, IsNil)
523 defer conn1.Close()
524 testWriteByte(c, conn1, '1')
525- conn2, err := testTlsDial(c, listenerAddr)
526+ conn2, err := testTlsDial(listenerAddr)
527 c.Assert(err, IsNil)
528 defer conn2.Close()
529 testWriteByte(c, conn2, '2')
530@@ -203,7 +195,7 @@
531 res, err := cmd.Output()
532 c.Assert(err, IsNil)
533 c.Assert(string(res), Matches, "(?s).*timed out.*")
534- conn2, err := testTlsDial(c, listenerAddr)
535+ conn2, err := testTlsDial(listenerAddr)
536 c.Assert(err, IsNil)
537 defer conn2.Close()
538 testWriteByte(c, conn2, '2')
539@@ -225,7 +217,7 @@
540 }, s.testlog)
541 }()
542 listenerAddr := lst.Addr().String()
543- _, err = testTlsDial(c, listenerAddr)
544+ _, err = testTlsDial(listenerAddr)
545 c.Assert(err, Not(IsNil))
546 lst.Close()
547 c.Check(<-errCh, ErrorMatches, ".*use of closed.*")
548@@ -244,7 +236,7 @@
549 }()
550 listenerAddr := lst.Addr().String()
551 c.Check(listenerAddr, Equals, foreignLst.Addr().String())
552- conn1, err := testTlsDial(c, listenerAddr)
553+ conn1, err := testTlsDial(listenerAddr)
554 c.Assert(err, IsNil)
555 defer conn1.Close()
556 testWriteByte(c, conn1, '1')
557
558=== modified file 'server/runner_devices.go'
559--- server/runner_devices.go 2014-03-12 12:34:18 +0000
560+++ server/runner_devices.go 2014-09-04 17:51:30 +0000
561@@ -17,7 +17,6 @@
562 package server
563
564 import (
565- "fmt"
566 "net"
567 "syscall"
568 "time"
569@@ -36,26 +35,8 @@
570 ParsedSessionQueueSize config.ConfigQueueSize `json:"session_queue_size"`
571 ParsedBrokerQueueSize config.ConfigQueueSize `json:"broker_queue_size"`
572 // device listener configuration
573- ParsedAddr config.ConfigHostPort `json:"addr"`
574- ParsedKeyPEMFile string `json:"key_pem_file"`
575- ParsedCertPEMFile string `json:"cert_pem_file"`
576- // private post-processed config
577- certPEMBlock []byte
578- keyPEMBlock []byte
579-}
580-
581-func (cfg *DevicesParsedConfig) FinishLoad(baseDir string) error {
582- keyPEMBlock, err := config.LoadFile(cfg.ParsedKeyPEMFile, baseDir)
583- if err != nil {
584- return fmt.Errorf("reading key_pem_file: %v", err)
585- }
586- certPEMBlock, err := config.LoadFile(cfg.ParsedCertPEMFile, baseDir)
587- if err != nil {
588- return fmt.Errorf("reading cert_pem_file: %v", err)
589- }
590- cfg.keyPEMBlock = keyPEMBlock
591- cfg.certPEMBlock = certPEMBlock
592- return nil
593+ ParsedAddr config.ConfigHostPort `json:"addr"`
594+ TLSParsedConfig
595 }
596
597 func (cfg *DevicesParsedConfig) PingInterval() time.Duration {
598@@ -78,14 +59,6 @@
599 return cfg.ParsedAddr.HostPort()
600 }
601
602-func (cfg *DevicesParsedConfig) KeyPEMBlock() []byte {
603- return cfg.keyPEMBlock
604-}
605-
606-func (cfg *DevicesParsedConfig) CertPEMBlock() []byte {
607- return cfg.certPEMBlock
608-}
609-
610 // DevicesRunner returns a function to accept device connections.
611 // If adoptLst is not nil it will be used as the underlying listener, instead
612 // of creating one, wrapped in a TLS layer.
613
614=== modified file 'server/runner_http.go'
615--- server/runner_http.go 2014-03-25 19:02:18 +0000
616+++ server/runner_http.go 2014-09-04 17:51:30 +0000
617@@ -17,6 +17,7 @@
618 package server
619
620 import (
621+ "crypto/tls"
622 "net"
623 "net/http"
624
625@@ -32,7 +33,8 @@
626
627 // HTTPServeRunner returns a function to serve HTTP requests.
628 // If httpLst is not nil it will be used as the underlying listener.
629-func HTTPServeRunner(httpLst net.Listener, h http.Handler, parsedCfg *HTTPServeParsedConfig) func() {
630+// If tlsCfg is not nit server over TLS with the config.
631+func HTTPServeRunner(httpLst net.Listener, h http.Handler, parsedCfg *HTTPServeParsedConfig, tlsCfg *tls.Config) func() {
632 if httpLst == nil {
633 var err error
634 httpLst, err = net.Listen("tcp", parsedCfg.ParsedHTTPAddr.HostPort())
635@@ -46,6 +48,9 @@
636 ReadTimeout: parsedCfg.ParsedHTTPReadTimeout.TimeDuration(),
637 WriteTimeout: parsedCfg.ParsedHTTPWriteTimeout.TimeDuration(),
638 }
639+ if tlsCfg != nil {
640+ httpLst = tls.NewListener(httpLst, tlsCfg)
641+ }
642 return func() {
643 err := srv.Serve(httpLst)
644 if err != nil {
645
646=== modified file 'server/runner_test.go'
647--- server/runner_test.go 2014-03-25 19:02:18 +0000
648+++ server/runner_test.go 2014-09-04 17:51:30 +0000
649@@ -17,6 +17,7 @@
650 package server
651
652 import (
653+ "crypto/tls"
654 "fmt"
655 "io/ioutil"
656 "net"
657@@ -68,7 +69,7 @@
658 func (s *runnerSuite) TestHTTPServeRunner(c *C) {
659 errCh := make(chan interface{}, 1)
660 h := http.HandlerFunc(testHandle)
661- runner := HTTPServeRunner(nil, h, &testHTTPServeParsedConfig)
662+ runner := HTTPServeRunner(nil, h, &testHTTPServeParsedConfig, nil)
663 c.Assert(s.lst, Not(IsNil))
664 defer s.lst.Close()
665 c.Check(s.kind, Equals, "http")
666@@ -89,16 +90,25 @@
667 c.Check(<-errCh, Matches, "accepting http connections:.*closed.*")
668 }
669
670+func cert() tls.Certificate {
671+ cert, err := tls.X509KeyPair(helpers.TestCertPEMBlock, helpers.TestKeyPEMBlock)
672+ if err != nil {
673+ panic(err)
674+ }
675+ return cert
676+}
677+
678 var testDevicesParsedConfig = DevicesParsedConfig{
679 ParsedPingInterval: config.ConfigTimeDuration{60 * time.Second},
680 ParsedExchangeTimeout: config.ConfigTimeDuration{10 * time.Second},
681 ParsedBrokerQueueSize: config.ConfigQueueSize(1000),
682 ParsedSessionQueueSize: config.ConfigQueueSize(10),
683 ParsedAddr: "127.0.0.1:0",
684- ParsedKeyPEMFile: "",
685- ParsedCertPEMFile: "",
686- keyPEMBlock: helpers.TestKeyPEMBlock,
687- certPEMBlock: helpers.TestCertPEMBlock,
688+ TLSParsedConfig: TLSParsedConfig{
689+ ParsedKeyPEMFile: "",
690+ ParsedCertPEMFile: "",
691+ cert: cert(),
692+ },
693 }
694
695 func (s *runnerSuite) TestDevicesRunner(c *C) {
696@@ -135,7 +145,36 @@
697 lst0, err := net.Listen("tcp", "127.0.0.1:0")
698 c.Assert(err, IsNil)
699 defer lst0.Close()
700- HTTPServeRunner(lst0, nil, &testHTTPServeParsedConfig)
701+ HTTPServeRunner(lst0, nil, &testHTTPServeParsedConfig, nil)
702 c.Assert(s.lst, Equals, lst0)
703 c.Check(s.kind, Equals, "http")
704 }
705+
706+func (s *runnerSuite) TestHTTPServeRunnerTLS(c *C) {
707+ errCh := make(chan interface{}, 1)
708+ h := http.HandlerFunc(testHandle)
709+ runner := HTTPServeRunner(nil, h, &testHTTPServeParsedConfig, helpers.TestTLSServerConfig)
710+ c.Assert(s.lst, Not(IsNil))
711+ defer s.lst.Close()
712+ c.Check(s.kind, Equals, "http")
713+ go func() {
714+ defer func() {
715+ errCh <- recover()
716+ }()
717+ runner()
718+ }()
719+ cli := http.Client{
720+ Transport: &http.Transport{
721+ TLSClientConfig: helpers.TestTLSClientConfig,
722+ },
723+ }
724+ resp, err := cli.Get(fmt.Sprintf("https://%s/", s.lst.Addr()))
725+ c.Assert(err, IsNil)
726+ defer resp.Body.Close()
727+ c.Assert(resp.StatusCode, Equals, 200)
728+ body, err := ioutil.ReadAll(resp.Body)
729+ c.Assert(err, IsNil)
730+ c.Check(string(body), Equals, "yay!\n")
731+ s.lst.Close()
732+ c.Check(<-errCh, Matches, "accepting http connections:.*closed.*")
733+}
734
735=== added file 'server/tlsconfig.go'
736--- server/tlsconfig.go 1970-01-01 00:00:00 +0000
737+++ server/tlsconfig.go 2014-09-04 17:51:30 +0000
738@@ -0,0 +1,53 @@
739+/*
740+ Copyright 2013-2014 Canonical Ltd.
741+
742+ This program is free software: you can redistribute it and/or modify it
743+ under the terms of the GNU General Public License version 3, as published
744+ by the Free Software Foundation.
745+
746+ This program is distributed in the hope that it will be useful, but
747+ WITHOUT ANY WARRANTY; without even the implied warranties of
748+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
749+ PURPOSE. See the GNU General Public License for more details.
750+
751+ You should have received a copy of the GNU General Public License along
752+ with this program. If not, see <http://www.gnu.org/licenses/>.
753+*/
754+
755+package server
756+
757+import (
758+ "crypto/tls"
759+ "fmt"
760+
761+ "launchpad.net/ubuntu-push/config"
762+)
763+
764+// A TLSParsedConfig holds and can be used to parse a tls server config.
765+type TLSParsedConfig struct {
766+ ParsedKeyPEMFile string `json:"key_pem_file"`
767+ ParsedCertPEMFile string `json:"cert_pem_file"`
768+ // private post-processed config
769+ cert tls.Certificate
770+}
771+
772+func (cfg *TLSParsedConfig) LoadPEMs(baseDir string) error {
773+ keyPEMBlock, err := config.LoadFile(cfg.ParsedKeyPEMFile, baseDir)
774+ if err != nil {
775+ return fmt.Errorf("reading key_pem_file: %v", err)
776+ }
777+ certPEMBlock, err := config.LoadFile(cfg.ParsedCertPEMFile, baseDir)
778+ if err != nil {
779+ return fmt.Errorf("reading cert_pem_file: %v", err)
780+ }
781+ cfg.cert, err = tls.X509KeyPair(certPEMBlock, keyPEMBlock)
782+ return err
783+}
784+
785+func (cfg *TLSParsedConfig) TLSServerConfig() *tls.Config {
786+ tlsCfg := &tls.Config{
787+ Certificates: []tls.Certificate{cfg.cert},
788+ SessionTicketsDisabled: true,
789+ }
790+ return tlsCfg
791+}
792
793=== modified file 'testing/tls.go'
794--- testing/tls.go 2014-01-21 21:36:07 +0000
795+++ testing/tls.go 2014-09-04 17:51:30 +0000
796@@ -16,26 +16,53 @@
797
798 package testing
799
800-// key&cert generated with go run /usr/lib/go/src/pkg/crypto/tls/generate_cert.go -ca -host localhost -rsa-bits 512 -duration 87600h
801+import (
802+ "crypto/tls"
803+ "crypto/x509"
804+)
805+
806+// 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
807 var (
808 TestKeyPEMBlock = []byte(`-----BEGIN RSA PRIVATE KEY-----
809-MIIBPAIBAAJBAPw+niki17X2qALE2A2AzE1q5dvK9CI4OduRtT9IgbFLC6psqAT2
810-1NA+QbY17nWSSpyP65zkMkwKXrbDzstwLPkCAwEAAQJAKwXbIBULScP6QA6m8xam
811-wgWbkvN41GVWqPafPV32kPBvKwSc+M1e+JR7g3/xPZE7TCELcfYi4yXEHZZI3Pbh
812-oQIhAP/UsgJbsfH1GFv8Y8qGl5l/kmwwkwHhuKvEC87Yur9FAiEA/GlQv3ZfaXnT
813-lcCFT0aL02O0RDiRYyMUG/JAZQJs6CUCIQCHO5SZYIUwxIGK5mCNxxXOAzyQSiD7
814-hqkKywf+4FvfDQIhALa0TLyqJFom0t7c4iIGAIRc8UlIYQSPiajI64+x9775AiEA
815-0v4fgSK/Rq059zW1753JjuB6aR0Uh+3RqJII4dUR1Wg=
816+MIIBOgIBAAJBANRU+pZKMNHpMvg549meJ060xQ4HCjrfVq+AeIER9W1pkaknDj8c
817+hwOWKHTeztcPF/LHVpKPabn+fSNbFlq+SzcCAwEAAQJBAIOO+4xu/3yv/rKqO7C0
818+Oyqa+pVMa1w60R0AfqmKFQTqiTgevM77uqjpW1+t0hpK20nyj6MUIPaL+9kZgp7t
819+mnECIQDqw79PXSzudf10XGy9ve5bRazINHxQYgJ7FvlTT6JhdQIhAOeJxq9zcKni
820+69ueO1ualz0hn8w6uHPsG9FlZ8C+7Jh7AiAWJgebjjfZ+4nA+6NKt2uQct9dOA5u
821+awC+6ij1ojK4rQIgNEqAbcWDj0qpe8sLms+aEntSjJxCZiPP0IW3XeeApZsCIDwo
822+x+YyxXQWJlf9L5TNYPRo+KFEdk3Cew0lv6QNs+xe
823 -----END RSA PRIVATE KEY-----`)
824
825 TestCertPEMBlock = []byte(`-----BEGIN CERTIFICATE-----
826 MIIBYzCCAQ+gAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
827-bzAeFw0xMzEyMTkyMDU1NDNaFw0yMzEyMTcyMDU1NDNaMBIxEDAOBgNVBAoTB0Fj
828-bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAPw+niki17X2qALE2A2AzE1q5dvK
829-9CI4OduRtT9IgbFLC6psqAT21NA+QbY17nWSSpyP65zkMkwKXrbDzstwLPkCAwEA
830-AaNUMFIwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
831-EwEB/wQFMAMBAf8wGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMAsGCSqGSIb3
832-DQEBBQNBAFqiVI+Km2XPSO+pxITaPvhmuzg+XG3l1+2di3gL+HlDobocjBqRctRU
833-YySO32W07acjGJmCHUKpCJuq9X8hpmk=
834+bzAeFw0xNDA4MjkxMjQyMDFaFw0yNDA4MjYxMjQyMDFaMBIxEDAOBgNVBAoTB0Fj
835+bWUgQ28wXDANBgkqhkiG9w0BAQEFAANLADBIAkEA1FT6lkow0eky+Dnj2Z4nTrTF
836+DgcKOt9Wr4B4gRH1bWmRqScOPxyHA5YodN7O1w8X8sdWko9puf59I1sWWr5LNwID
837+AQABo1IwUDAOBgNVHQ8BAf8EBAMCAKQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYD
838+VR0TAQH/BAUwAwEB/zAYBgNVHREEETAPgg1wdXNoLWRlbGl2ZXJ5MAsGCSqGSIb3
839+DQEBBQNBABtWCdMFkhIO8+oM3vugOWle9WJZ1FCRWD+cMl76mI1lhmNF4lvEZG47
840+xUjekA1+heU39WpOEzZSybrOdiEaGbI=
841 -----END CERTIFICATE-----`)
842 )
843+
844+// test tls server config
845+var TestTLSServerConfig, TestTLSClientConfig *tls.Config
846+
847+func init() {
848+ cert, err := tls.X509KeyPair(TestCertPEMBlock, TestKeyPEMBlock)
849+ if err != nil {
850+ panic(err)
851+ }
852+ TestTLSServerConfig = &tls.Config{
853+ Certificates: []tls.Certificate{cert},
854+ }
855+ cp := x509.NewCertPool()
856+ ok := cp.AppendCertsFromPEM(TestCertPEMBlock)
857+ if !ok {
858+ panic("failed to parse test cert")
859+ }
860+ TestTLSClientConfig = &tls.Config{
861+ RootCAs: cp,
862+ ServerName: "push-delivery",
863+ }
864+}

Subscribers

People subscribed via source and target branches