~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/gopkg.in/macaroon-bakery.v1/bakery/service_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package bakery_test
 
2
 
 
3
import (
 
4
        "encoding/json"
 
5
        "fmt"
 
6
 
 
7
        "github.com/juju/testing"
 
8
        jc "github.com/juju/testing/checkers"
 
9
        gc "gopkg.in/check.v1"
 
10
        "gopkg.in/macaroon.v1"
 
11
 
 
12
        "gopkg.in/macaroon-bakery.v1/bakery"
 
13
        "gopkg.in/macaroon-bakery.v1/bakery/checkers"
 
14
)
 
15
 
 
16
type ServiceSuite struct {
 
17
        testing.CleanupSuite
 
18
}
 
19
 
 
20
var _ = gc.Suite(&ServiceSuite{})
 
21
 
 
22
// TestSingleServiceFirstParty creates a single service
 
23
// with a macaroon with one first party caveat.
 
24
// It creates a request with this macaroon and checks that the service
 
25
// can verify this macaroon as valid.
 
26
func (s *ServiceSuite) TestSingleServiceFirstParty(c *gc.C) {
 
27
        p := bakery.NewServiceParams{
 
28
                Location: "loc",
 
29
                Store:    nil,
 
30
                Key:      nil,
 
31
                Locator:  nil,
 
32
        }
 
33
        service, err := bakery.NewService(p)
 
34
        c.Assert(err, gc.IsNil)
 
35
 
 
36
        primary, err := service.NewMacaroon("", nil, nil)
 
37
        c.Assert(err, gc.IsNil)
 
38
        c.Assert(primary.Location(), gc.Equals, "loc")
 
39
        cav := checkers.Caveat{
 
40
                Location:  "",
 
41
                Condition: "something",
 
42
        }
 
43
        err = service.AddCaveat(primary, cav)
 
44
        c.Assert(err, gc.IsNil)
 
45
 
 
46
        err = service.Check(macaroon.Slice{primary}, strcmpChecker("something"))
 
47
        c.Assert(err, gc.IsNil)
 
48
}
 
49
 
 
50
// TestMacaroonPaperFig6 implements an example flow as described in the macaroons paper:
 
51
// http://theory.stanford.edu/~ataly/Papers/macaroons.pdf
 
52
// There are three services, ts, fs, as:
 
53
// ts is a storage service which has deligated authority to a forum service fs.
 
54
// The forum service wants to require its users to be logged into to an authentication service as.
 
55
//
 
56
// The client obtains a macaroon from fs (minted by ts, with a third party caveat addressed to as).
 
57
// The client obtains a discharge macaroon from as to satisfy this caveat.
 
58
// The target service verifies the original macaroon it delegated to fs
 
59
// No direct contact between as and ts is required
 
60
func (s *ServiceSuite) TestMacaroonPaperFig6(c *gc.C) {
 
61
        locator := make(bakery.PublicKeyLocatorMap)
 
62
        as := newService(c, "as-loc", locator)
 
63
        ts := newService(c, "ts-loc", locator)
 
64
        fs := newService(c, "fs-loc", locator)
 
65
 
 
66
        // ts creates a macaroon.
 
67
        tsMacaroon, err := ts.NewMacaroon("", nil, nil)
 
68
        c.Assert(err, gc.IsNil)
 
69
 
 
70
        // ts somehow sends the macaroon to fs which adds a third party caveat to be discharged by as.
 
71
        err = fs.AddCaveat(tsMacaroon, checkers.Caveat{Location: "as-loc", Condition: "user==bob"})
 
72
        c.Assert(err, gc.IsNil)
 
73
 
 
74
        // client asks for a discharge macaroon for each third party caveat
 
75
        d, err := bakery.DischargeAll(tsMacaroon, func(firstPartyLocation string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
 
76
                c.Assert(firstPartyLocation, gc.Equals, "ts-loc")
 
77
                c.Assert(cav.Location, gc.Equals, "as-loc")
 
78
                mac, err := as.Discharge(strcmpChecker("user==bob"), cav.Id)
 
79
                c.Assert(err, gc.IsNil)
 
80
                return mac, nil
 
81
        })
 
82
        c.Assert(err, gc.IsNil)
 
83
 
 
84
        err = ts.Check(d, strcmpChecker(""))
 
85
        c.Assert(err, gc.IsNil)
 
86
}
 
87
 
 
88
func macStr(m *macaroon.Macaroon) string {
 
89
        data, err := json.MarshalIndent(m, "\t", "\t")
 
90
        if err != nil {
 
91
                panic(err)
 
92
        }
 
93
        return string(data)
 
94
}
 
95
 
 
96
// TestMacaroonPaperFig6FailsWithoutDischarges runs a similar test as TestMacaroonPaperFig6
 
97
// without the client discharging the third party caveats.
 
98
func (s *ServiceSuite) TestMacaroonPaperFig6FailsWithoutDischarges(c *gc.C) {
 
99
        locator := make(bakery.PublicKeyLocatorMap)
 
100
        ts := newService(c, "ts-loc", locator)
 
101
        fs := newService(c, "fs-loc", locator)
 
102
        _ = newService(c, "as-loc", locator)
 
103
 
 
104
        // ts creates a macaroon.
 
105
        tsMacaroon, err := ts.NewMacaroon("", nil, nil)
 
106
        c.Assert(err, gc.IsNil)
 
107
 
 
108
        // ts somehow sends the macaroon to fs which adds a third party caveat to be discharged by as.
 
109
        err = fs.AddCaveat(tsMacaroon, checkers.Caveat{Location: "as-loc", Condition: "user==bob"})
 
110
        c.Assert(err, gc.IsNil)
 
111
 
 
112
        // client makes request to ts
 
113
        err = ts.Check(macaroon.Slice{tsMacaroon}, strcmpChecker(""))
 
114
        c.Assert(err, gc.ErrorMatches, `verification failed: cannot find discharge macaroon for caveat ".*"`)
 
115
}
 
116
 
 
117
// TestMacaroonPaperFig6FailsWithBindingOnTamperedSignature runs a similar test as TestMacaroonPaperFig6
 
118
// with the discharge macaroon binding being done on a tampered signature.
 
119
func (s *ServiceSuite) TestMacaroonPaperFig6FailsWithBindingOnTamperedSignature(c *gc.C) {
 
120
        locator := make(bakery.PublicKeyLocatorMap)
 
121
        as := newService(c, "as-loc", locator)
 
122
        ts := newService(c, "ts-loc", locator)
 
123
        fs := newService(c, "fs-loc", locator)
 
124
 
 
125
        // ts creates a macaroon.
 
126
        tsMacaroon, err := ts.NewMacaroon("", nil, nil)
 
127
        c.Assert(err, gc.IsNil)
 
128
 
 
129
        // ts somehow sends the macaroon to fs which adds a third party caveat to be discharged by as.
 
130
        err = fs.AddCaveat(tsMacaroon, checkers.Caveat{Location: "as-loc", Condition: "user==bob"})
 
131
        c.Assert(err, gc.IsNil)
 
132
 
 
133
        // client asks for a discharge macaroon for each third party caveat
 
134
        d, err := bakery.DischargeAll(tsMacaroon, func(firstPartyLocation string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
 
135
                c.Assert(firstPartyLocation, gc.Equals, "ts-loc")
 
136
                c.Assert(cav.Location, gc.Equals, "as-loc")
 
137
                mac, err := as.Discharge(strcmpChecker("user==bob"), cav.Id)
 
138
                c.Assert(err, gc.IsNil)
 
139
                return mac, nil
 
140
        })
 
141
        c.Assert(err, gc.IsNil)
 
142
 
 
143
        // client has all the discharge macaroons. For each discharge macaroon bind it to our tsMacaroon
 
144
        // and add it to our request.
 
145
        for _, dm := range d[1:] {
 
146
                dm.Bind([]byte("tampered-signature")) // Bind against an incorrect signature.
 
147
        }
 
148
 
 
149
        // client makes request to ts.
 
150
        err = ts.Check(d, strcmpChecker(""))
 
151
        c.Assert(err, gc.ErrorMatches, "verification failed: signature mismatch after caveat verification")
 
152
}
 
153
 
 
154
func (s *ServiceSuite) TestNeedDeclared(c *gc.C) {
 
155
        locator := make(bakery.PublicKeyLocatorMap)
 
156
        firstParty := newService(c, "first", locator)
 
157
        thirdParty := newService(c, "third", locator)
 
158
 
 
159
        // firstParty mints a macaroon with a third-party caveat addressed
 
160
        // to thirdParty with a need-declared caveat.
 
161
        m, err := firstParty.NewMacaroon("", nil, []checkers.Caveat{
 
162
                checkers.NeedDeclaredCaveat(checkers.Caveat{
 
163
                        Location:  "third",
 
164
                        Condition: "something",
 
165
                }, "foo", "bar"),
 
166
        })
 
167
        c.Assert(err, gc.IsNil)
 
168
 
 
169
        // The client asks for a discharge macaroon for each third party caveat.
 
170
        d, err := bakery.DischargeAll(m, func(_ string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
 
171
                return thirdParty.Discharge(strcmpChecker("something"), cav.Id)
 
172
        })
 
173
        c.Assert(err, gc.IsNil)
 
174
 
 
175
        // The required declared attributes should have been added
 
176
        // to the discharge macaroons.
 
177
        declared := checkers.InferDeclared(d)
 
178
        c.Assert(declared, gc.DeepEquals, checkers.Declared{
 
179
                "foo": "",
 
180
                "bar": "",
 
181
        })
 
182
 
 
183
        // Make sure the macaroons actually check out correctly
 
184
        // when provided with the declared checker.
 
185
        err = firstParty.Check(d, checkers.New(declared))
 
186
        c.Assert(err, gc.IsNil)
 
187
 
 
188
        // Try again when the third party does add a required declaration.
 
189
 
 
190
        // The client asks for a discharge macaroon for each third party caveat.
 
191
        d, err = bakery.DischargeAll(m, func(_ string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
 
192
                checker := thirdPartyCheckerWithCaveats{
 
193
                        checkers.DeclaredCaveat("foo", "a"),
 
194
                        checkers.DeclaredCaveat("arble", "b"),
 
195
                }
 
196
                return thirdParty.Discharge(checker, cav.Id)
 
197
        })
 
198
        c.Assert(err, gc.IsNil)
 
199
 
 
200
        // One attribute should have been added, the other was already there.
 
201
        declared = checkers.InferDeclared(d)
 
202
        c.Assert(declared, gc.DeepEquals, checkers.Declared{
 
203
                "foo":   "a",
 
204
                "bar":   "",
 
205
                "arble": "b",
 
206
        })
 
207
 
 
208
        err = firstParty.Check(d, checkers.New(declared))
 
209
        c.Assert(err, gc.IsNil)
 
210
 
 
211
        // Try again, but this time pretend a client is sneakily trying
 
212
        // to add another "declared" attribute to alter the declarations.
 
213
        d, err = bakery.DischargeAll(m, func(_ string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
 
214
                checker := thirdPartyCheckerWithCaveats{
 
215
                        checkers.DeclaredCaveat("foo", "a"),
 
216
                        checkers.DeclaredCaveat("arble", "b"),
 
217
                }
 
218
                m, err := thirdParty.Discharge(checker, cav.Id)
 
219
                c.Assert(err, gc.IsNil)
 
220
 
 
221
                // Sneaky client adds a first party caveat.
 
222
                m.AddFirstPartyCaveat(checkers.DeclaredCaveat("foo", "c").Condition)
 
223
                return m, nil
 
224
        })
 
225
        c.Assert(err, gc.IsNil)
 
226
 
 
227
        declared = checkers.InferDeclared(d)
 
228
        c.Assert(declared, gc.DeepEquals, checkers.Declared{
 
229
                "bar":   "",
 
230
                "arble": "b",
 
231
        })
 
232
 
 
233
        err = firstParty.Check(d, checkers.New(declared))
 
234
        c.Assert(err, gc.ErrorMatches, `verification failed: caveat "declared foo a" not satisfied: got foo=null, expected "a"`)
 
235
}
 
236
 
 
237
func (s *ServiceSuite) TestDischargeTwoNeedDeclared(c *gc.C) {
 
238
        locator := make(bakery.PublicKeyLocatorMap)
 
239
        firstParty := newService(c, "first", locator)
 
240
        thirdParty := newService(c, "third", locator)
 
241
 
 
242
        // firstParty mints a macaroon with two third party caveats
 
243
        // with overlapping attributes.
 
244
        m, err := firstParty.NewMacaroon("", nil, []checkers.Caveat{
 
245
                checkers.NeedDeclaredCaveat(checkers.Caveat{
 
246
                        Location:  "third",
 
247
                        Condition: "x",
 
248
                }, "foo", "bar"),
 
249
                checkers.NeedDeclaredCaveat(checkers.Caveat{
 
250
                        Location:  "third",
 
251
                        Condition: "y",
 
252
                }, "bar", "baz"),
 
253
        })
 
254
        c.Assert(err, gc.IsNil)
 
255
 
 
256
        // The client asks for a discharge macaroon for each third party caveat.
 
257
        // Since no declarations are added by the discharger,
 
258
        d, err := bakery.DischargeAll(m, func(_ string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
 
259
                return thirdParty.Discharge(bakery.ThirdPartyCheckerFunc(func(_, caveat string) ([]checkers.Caveat, error) {
 
260
                        return nil, nil
 
261
                }), cav.Id)
 
262
        })
 
263
        c.Assert(err, gc.IsNil)
 
264
        declared := checkers.InferDeclared(d)
 
265
        c.Assert(declared, gc.DeepEquals, checkers.Declared{
 
266
                "foo": "",
 
267
                "bar": "",
 
268
                "baz": "",
 
269
        })
 
270
        err = firstParty.Check(d, checkers.New(declared))
 
271
        c.Assert(err, gc.IsNil)
 
272
 
 
273
        // If they return conflicting values, the discharge fails.
 
274
        // The client asks for a discharge macaroon for each third party caveat.
 
275
        // Since no declarations are added by the discharger,
 
276
        d, err = bakery.DischargeAll(m, func(_ string, cav macaroon.Caveat) (*macaroon.Macaroon, error) {
 
277
                return thirdParty.Discharge(bakery.ThirdPartyCheckerFunc(func(_, caveat string) ([]checkers.Caveat, error) {
 
278
                        switch caveat {
 
279
                        case "x":
 
280
                                return []checkers.Caveat{
 
281
                                        checkers.DeclaredCaveat("foo", "fooval1"),
 
282
                                }, nil
 
283
                        case "y":
 
284
                                return []checkers.Caveat{
 
285
                                        checkers.DeclaredCaveat("foo", "fooval2"),
 
286
                                        checkers.DeclaredCaveat("baz", "bazval"),
 
287
                                }, nil
 
288
                        }
 
289
                        return nil, fmt.Errorf("not matched")
 
290
                }), cav.Id)
 
291
        })
 
292
        c.Assert(err, gc.IsNil)
 
293
        declared = checkers.InferDeclared(d)
 
294
        c.Assert(declared, gc.DeepEquals, checkers.Declared{
 
295
                "bar": "",
 
296
                "baz": "bazval",
 
297
        })
 
298
        err = firstParty.Check(d, checkers.New(declared))
 
299
        c.Assert(err, gc.ErrorMatches, `verification failed: caveat "declared foo fooval1" not satisfied: got foo=null, expected "fooval1"`)
 
300
}
 
301
 
 
302
func (s *ServiceSuite) TestDischargeMacaroonCannotBeUsedAsNormalMacaroon(c *gc.C) {
 
303
        locator := make(bakery.PublicKeyLocatorMap)
 
304
        firstParty := newService(c, "first", locator)
 
305
        thirdParty := newService(c, "third", locator)
 
306
 
 
307
        // First party mints a macaroon with a 3rd party caveat.
 
308
        m, err := firstParty.NewMacaroon("", nil, []checkers.Caveat{{
 
309
                Location:  "third",
 
310
                Condition: "true",
 
311
        }})
 
312
        c.Assert(err, gc.IsNil)
 
313
 
 
314
        // Acquire the discharge macaroon, but don't bind it to the original.
 
315
        d, err := thirdParty.Discharge(bakery.ThirdPartyCheckerFunc(func(_, caveat string) ([]checkers.Caveat, error) {
 
316
                return nil, nil
 
317
        }), m.Caveats()[0].Id)
 
318
        c.Assert(err, gc.IsNil)
 
319
 
 
320
        // Make sure it cannot be used as a normal macaroon in the third party.
 
321
        err = thirdParty.Check(macaroon.Slice{d}, checkers.New())
 
322
        c.Assert(err, gc.ErrorMatches, `verification failed: macaroon not found in storage`)
 
323
}
 
324
 
 
325
func (*ServiceSuite) TestCheckAny(c *gc.C) {
 
326
        svc := newService(c, "somewhere", nil)
 
327
        newMacaroons := func(id string, caveats ...checkers.Caveat) macaroon.Slice {
 
328
                m, err := svc.NewMacaroon(id, nil, caveats)
 
329
                c.Assert(err, gc.IsNil)
 
330
                return macaroon.Slice{m}
 
331
        }
 
332
        tests := []struct {
 
333
                about          string
 
334
                macaroons      []macaroon.Slice
 
335
                assert         map[string]string
 
336
                checker        checkers.Checker
 
337
                expectDeclared map[string]string
 
338
                expectId       string
 
339
                expectError    string
 
340
        }{{
 
341
                about:       "no macaroons",
 
342
                expectError: "verification failed: no macaroons",
 
343
        }, {
 
344
                about: "one macaroon, no caveats",
 
345
                macaroons: []macaroon.Slice{
 
346
                        newMacaroons("x1"),
 
347
                },
 
348
                expectId: "x1",
 
349
        }, {
 
350
                about: "one macaroon, one unrecognized caveat",
 
351
                macaroons: []macaroon.Slice{
 
352
                        newMacaroons("x2", checkers.Caveat{
 
353
                                Condition: "bad",
 
354
                        }),
 
355
                },
 
356
                expectError: `verification failed: caveat "bad" not satisfied: caveat not recognized`,
 
357
        }, {
 
358
                about: "two macaroons, only one ok",
 
359
                macaroons: []macaroon.Slice{
 
360
                        newMacaroons("x3", checkers.Caveat{
 
361
                                Condition: "bad",
 
362
                        }),
 
363
                        newMacaroons("y3"),
 
364
                },
 
365
                expectId: "y3",
 
366
        }, {
 
367
                about: "macaroon with declared caveats",
 
368
                macaroons: []macaroon.Slice{
 
369
                        newMacaroons("x4",
 
370
                                checkers.DeclaredCaveat("key1", "value1"),
 
371
                                checkers.DeclaredCaveat("key2", "value2"),
 
372
                        ),
 
373
                },
 
374
                expectDeclared: map[string]string{
 
375
                        "key1": "value1",
 
376
                        "key2": "value2",
 
377
                },
 
378
                expectId: "x4",
 
379
        }, {
 
380
                about: "macaroon with declared values and asserted keys with wrong value",
 
381
                macaroons: []macaroon.Slice{
 
382
                        newMacaroons("x5",
 
383
                                checkers.DeclaredCaveat("key1", "value1"),
 
384
                                checkers.DeclaredCaveat("key2", "value2"),
 
385
                        ),
 
386
                },
 
387
                assert: map[string]string{
 
388
                        "key1": "valuex",
 
389
                },
 
390
                expectId:    "x5",
 
391
                expectError: `verification failed: caveat "declared key1 value1" not satisfied: got key1="valuex", expected "value1"`,
 
392
        }, {
 
393
                about: "macaroon with declared values and asserted keys with correct value",
 
394
                macaroons: []macaroon.Slice{
 
395
                        newMacaroons("x6",
 
396
                                checkers.DeclaredCaveat("key1", "value1"),
 
397
                                checkers.DeclaredCaveat("key2", "value2"),
 
398
                        ),
 
399
                },
 
400
                assert: map[string]string{
 
401
                        "key1": "value1",
 
402
                },
 
403
                expectDeclared: map[string]string{
 
404
                        "key1": "value1",
 
405
                        "key2": "value2",
 
406
                },
 
407
                expectId: "x6",
 
408
        }}
 
409
        for i, test := range tests {
 
410
                c.Logf("test %d: %s", i, test.about)
 
411
                if test.expectDeclared == nil {
 
412
                        test.expectDeclared = make(map[string]string)
 
413
                }
 
414
                if test.checker == nil {
 
415
                        test.checker = checkers.New()
 
416
                }
 
417
 
 
418
                decl, ms, err := svc.CheckAnyM(test.macaroons, test.assert, test.checker)
 
419
                if test.expectError != "" {
 
420
                        c.Assert(err, gc.ErrorMatches, test.expectError)
 
421
                        c.Assert(decl, gc.HasLen, 0)
 
422
                        c.Assert(ms, gc.IsNil)
 
423
                        continue
 
424
                }
 
425
                c.Assert(err, gc.IsNil)
 
426
                c.Assert(decl, jc.DeepEquals, test.expectDeclared)
 
427
                c.Assert(ms[0].Id(), gc.Equals, test.expectId)
 
428
        }
 
429
}
 
430
 
 
431
func (s *ServiceSuite) TestNewMacaroonWithRootKeyStorage(c *gc.C) {
 
432
        svc, err := bakery.NewService(bakery.NewServiceParams{
 
433
                Location: "somewhere",
 
434
        })
 
435
        c.Assert(err, gc.IsNil)
 
436
 
 
437
        store := bakery.NewMemRootKeyStorage()
 
438
        key, id, err := store.RootKey()
 
439
        c.Assert(err, gc.IsNil)
 
440
 
 
441
        svc = svc.WithRootKeyStore(store)
 
442
 
 
443
        m, err := svc.NewMacaroon("", nil, []checkers.Caveat{{
 
444
                Location:  "",
 
445
                Condition: "something",
 
446
        }})
 
447
        c.Assert(err, gc.IsNil)
 
448
        c.Assert(m.Location(), gc.Equals, "somewhere")
 
449
        id1 := m.Id()
 
450
        c.Assert(id1, gc.Matches, id+"-[0-9a-f]{32}")
 
451
 
 
452
        err = svc.Check(macaroon.Slice{m}, strcmpChecker("something"))
 
453
        c.Assert(err, gc.IsNil)
 
454
 
 
455
        // Check that it's really using the root key returned from
 
456
        // the store.
 
457
        err = m.Verify(key, func(string) error {
 
458
                return nil
 
459
        }, nil)
 
460
        c.Assert(err, gc.IsNil)
 
461
 
 
462
        // Create another one and check that it re-uses the
 
463
        // same key but has a different id.
 
464
        m, err = svc.NewMacaroon("", nil, []checkers.Caveat{{
 
465
                Location:  "",
 
466
                Condition: "something",
 
467
        }})
 
468
        c.Assert(err, gc.IsNil)
 
469
        c.Assert(m.Location(), gc.Equals, "somewhere")
 
470
        id2 := m.Id()
 
471
        c.Assert(id2, gc.Matches, id+"-[0-9a-f]{32}")
 
472
        c.Assert(id2, gc.Not(gc.Equals), id1)
 
473
        err = m.Verify(key, func(string) error { return nil }, nil)
 
474
        c.Assert(err, gc.IsNil)
 
475
}
 
476
 
 
477
func (s *ServiceSuite) TestNewMacaroonWithRootKeyStorageInParams(c *gc.C) {
 
478
        store := bakery.NewMemRootKeyStorage()
 
479
        _, id, err := store.RootKey()
 
480
        c.Assert(err, gc.IsNil)
 
481
 
 
482
        // Check that we can create a bakery with the root key store
 
483
        // in its parameters too.
 
484
        svc, err := bakery.NewService(bakery.NewServiceParams{
 
485
                Location:     "elsewhere",
 
486
                RootKeyStore: store,
 
487
        })
 
488
        c.Assert(err, gc.IsNil)
 
489
 
 
490
        m, err := svc.NewMacaroon("", nil, nil)
 
491
        c.Assert(err, gc.IsNil)
 
492
        c.Assert(m.Id(), gc.Matches, id+"-[0-9a-f]{32}")
 
493
 
 
494
        err = svc.Check(macaroon.Slice{m}, checkers.New())
 
495
        c.Assert(err, gc.IsNil)
 
496
}
 
497
 
 
498
func (s *ServiceSuite) TestNewMacaroonWithExplicitIdAndRootKeyStorage(c *gc.C) {
 
499
        store := bakery.NewMemRootKeyStorage()
 
500
 
 
501
        // Check that we can create a bakery with the root key store
 
502
        // in its parameters too.
 
503
        svc, err := bakery.NewService(bakery.NewServiceParams{
 
504
                Location:     "somewhere",
 
505
                RootKeyStore: store,
 
506
        })
 
507
        c.Assert(err, gc.IsNil)
 
508
 
 
509
        m, err := svc.NewMacaroon("someid", nil, nil)
 
510
        c.Assert(err, gc.ErrorMatches, `cannot choose root key or id when using RootKeyStore`)
 
511
        c.Assert(m, gc.IsNil)
 
512
 
 
513
        m, err = svc.NewMacaroon("", []byte{1}, nil)
 
514
        c.Assert(err, gc.ErrorMatches, `cannot choose root key or id when using RootKeyStore`)
 
515
        c.Assert(m, gc.IsNil)
 
516
}
 
517
 
 
518
func newService(c *gc.C, location string, locator bakery.PublicKeyLocatorMap) *bakery.Service {
 
519
        keyPair, err := bakery.GenerateKey()
 
520
        c.Assert(err, gc.IsNil)
 
521
 
 
522
        svc, err := bakery.NewService(bakery.NewServiceParams{
 
523
                Location: location,
 
524
                Key:      keyPair,
 
525
                Locator:  locator,
 
526
        })
 
527
        c.Assert(err, gc.IsNil)
 
528
        if locator != nil {
 
529
                locator[location] = &keyPair.Public
 
530
        }
 
531
        return svc
 
532
}
 
533
 
 
534
type strcmpChecker string
 
535
 
 
536
func (c strcmpChecker) CheckFirstPartyCaveat(caveat string) error {
 
537
        if caveat != string(c) {
 
538
                return fmt.Errorf("%v doesn't match %s", caveat, c)
 
539
        }
 
540
        return nil
 
541
}
 
542
 
 
543
func (c strcmpChecker) CheckThirdPartyCaveat(caveatId string, caveat string) ([]checkers.Caveat, error) {
 
544
        if caveat != string(c) {
 
545
                return nil, fmt.Errorf("%v doesn't match %s", caveat, c)
 
546
        }
 
547
        return nil, nil
 
548
}
 
549
 
 
550
type thirdPartyCheckerWithCaveats []checkers.Caveat
 
551
 
 
552
func (c thirdPartyCheckerWithCaveats) CheckThirdPartyCaveat(caveatId string, caveat string) ([]checkers.Caveat, error) {
 
553
        return c, nil
 
554
}