forked from lightninglabs/aperture
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcaveat_test.go
More file actions
202 lines (183 loc) · 4.7 KB
/
caveat_test.go
File metadata and controls
202 lines (183 loc) · 4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package lsat
import (
"errors"
"testing"
"gopkg.in/macaroon.v2"
)
var (
testMacaroon, _ = macaroon.New(nil, nil, "", macaroon.LatestVersion)
)
// TestCaveatSerialization ensures that we can properly encode/decode valid
// caveats and cannot do so for invalid ones.
func TestCaveatSerialization(t *testing.T) {
t.Parallel()
tests := []struct {
name string
caveatStr string
err error
}{
{
name: "valid caveat",
caveatStr: "expiration=1337",
err: nil,
},
{
name: "valid caveat with separator in value",
caveatStr: "expiration=1337=",
err: nil,
},
{
name: "invalid caveat",
caveatStr: "expiration:1337",
err: ErrInvalidCaveat,
},
}
for _, test := range tests {
test := test
success := t.Run(test.name, func(t *testing.T) {
caveat, err := DecodeCaveat(test.caveatStr)
if !errors.Is(err, test.err) {
t.Fatalf("expected err \"%v\", got \"%v\"",
test.err, err)
}
if test.err != nil {
return
}
caveatStr := EncodeCaveat(caveat)
if caveatStr != test.caveatStr {
t.Fatalf("expected encoded caveat \"%v\", "+
"got \"%v\"", test.caveatStr, caveatStr)
}
})
if !success {
return
}
}
}
// TestHasCaveat ensures we can determine whether a macaroon contains a caveat
// with a specific condition.
func TestHasCaveat(t *testing.T) {
t.Parallel()
const (
cond = "cond"
value = "value"
)
m := testMacaroon.Clone()
// The macaroon doesn't have any caveats, so we shouldn't find any.
if _, ok := HasCaveat(m, cond); ok {
t.Fatal("found unexpected caveat with unknown condition")
}
// Add two caveats, one in a valid LSAT format and another invalid.
// We'll test that we're still able to determine the macaroon contains
// the valid caveat even though there is one that is invalid.
invalidCaveat := []byte("invalid")
if err := m.AddFirstPartyCaveat(invalidCaveat); err != nil {
t.Fatalf("unable to add macaroon caveat: %v", err)
}
validCaveat1 := Caveat{Condition: cond, Value: value}
if err := AddFirstPartyCaveats(m, validCaveat1); err != nil {
t.Fatalf("unable to add macaroon caveat: %v", err)
}
caveatValue, ok := HasCaveat(m, cond)
if !ok {
t.Fatal("expected macaroon to contain caveat")
}
if caveatValue != validCaveat1.Value {
t.Fatalf("expected caveat value \"%v\", got \"%v\"",
validCaveat1.Value, caveatValue)
}
// If we add another caveat with the same condition, the value of the
// most recently added caveat should be returned instead.
validCaveat2 := validCaveat1
validCaveat2.Value += value
if err := AddFirstPartyCaveats(m, validCaveat2); err != nil {
t.Fatalf("unable to add macaroon caveat: %v", err)
}
caveatValue, ok = HasCaveat(m, cond)
if !ok {
t.Fatal("expected macaroon to contain caveat")
}
if caveatValue != validCaveat2.Value {
t.Fatalf("expected caveat value \"%v\", got \"%v\"",
validCaveat2.Value, caveatValue)
}
}
// TestVerifyCaveats ensures caveat verification only holds true for known
// caveats.
func TestVerifyCaveats(t *testing.T) {
t.Parallel()
caveat1 := Caveat{Condition: "1", Value: "test"}
caveat2 := Caveat{Condition: "2", Value: "test"}
satisfier := Satisfier{
Condition: caveat1.Condition,
SatisfyPrevious: func(c Caveat, prev Caveat) error {
return nil
},
SatisfyFinal: func(c Caveat) error {
return nil
},
}
invalidSatisfyPrevious := func(c Caveat, prev Caveat) error {
return errors.New("no")
}
invalidSatisfyFinal := func(c Caveat) error {
return errors.New("no")
}
tests := []struct {
name string
caveats []Caveat
satisfiers []Satisfier
shouldFail bool
}{
{
name: "simple verification",
caveats: []Caveat{caveat1},
satisfiers: []Satisfier{satisfier},
shouldFail: false,
},
{
name: "unknown caveat",
caveats: []Caveat{caveat1, caveat2},
satisfiers: []Satisfier{satisfier},
shouldFail: false,
},
{
name: "one invalid",
caveats: []Caveat{caveat1, caveat2},
satisfiers: []Satisfier{
satisfier,
{
Condition: caveat2.Condition,
SatisfyFinal: invalidSatisfyFinal,
},
},
shouldFail: true,
},
{
name: "prev invalid",
caveats: []Caveat{caveat1, caveat1},
satisfiers: []Satisfier{
{
Condition: caveat1.Condition,
SatisfyPrevious: invalidSatisfyPrevious,
},
},
shouldFail: true,
},
}
for _, test := range tests {
test := test
success := t.Run(test.name, func(t *testing.T) {
err := VerifyCaveats(test.caveats, test.satisfiers...)
if test.shouldFail && err == nil {
t.Fatal("expected caveat verification to fail")
}
if !test.shouldFail && err != nil {
t.Fatal("unexpected caveat verification failure")
}
})
if !success {
return
}
}
}