Merge lp:~pedronis/ubuntu-push/http-ssl into lp:ubuntu-push
- http-ssl
- Merge into trunk
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 |
Related bugs: |
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.
- 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 | +} |