11
11
# limitations under the License.
12
12
13
13
import json
14
+ import os
15
+ import time
14
16
15
17
import pretend
18
+ import pymacaroons
16
19
import pytest
17
20
18
21
from pymacaroons .exceptions import MacaroonInvalidSignatureException
19
22
20
- from warehouse .macaroons .caveats import Caveat , InvalidMacaroonError , V1Caveat , Verifier
23
+ from warehouse .macaroons .caveats import Caveat , ExpiryCaveat , V1Caveat , Verifier
21
24
22
25
from ...common .db .packaging import ProjectFactory
23
26
@@ -28,10 +31,8 @@ def test_creation(self):
28
31
caveat = Caveat (verifier )
29
32
30
33
assert caveat .verifier is verifier
31
- with pytest .raises (InvalidMacaroonError ):
32
- caveat .verify (pretend .stub ())
33
- with pytest .raises (InvalidMacaroonError ):
34
- caveat (pretend .stub ())
34
+ assert caveat .verify (pretend .stub ()) is False
35
+ assert caveat (pretend .stub ()) is False
35
36
36
37
37
38
class TestV1Caveat :
@@ -47,8 +48,7 @@ def test_verify_invalid_predicates(self, predicate, result):
47
48
verifier = pretend .stub ()
48
49
caveat = V1Caveat (verifier )
49
50
50
- with pytest .raises (InvalidMacaroonError ):
51
- caveat (predicate )
51
+ assert caveat (predicate ) is False
52
52
53
53
def test_verify_valid_predicate (self ):
54
54
verifier = pretend .stub ()
@@ -62,17 +62,17 @@ def test_verify_project_invalid_context(self):
62
62
caveat = V1Caveat (verifier )
63
63
64
64
predicate = {"version" : 1 , "permissions" : {"projects" : ["notfoobar" ]}}
65
- with pytest . raises ( InvalidMacaroonError ):
66
- caveat (json .dumps (predicate ))
65
+
66
+ assert caveat (json .dumps (predicate )) is False
67
67
68
68
def test_verify_project_invalid_project_name (self , db_request ):
69
69
project = ProjectFactory .create (name = "foobar" )
70
70
verifier = pretend .stub (context = project )
71
71
caveat = V1Caveat (verifier )
72
72
73
73
predicate = {"version" : 1 , "permissions" : {"projects" : ["notfoobar" ]}}
74
- with pytest . raises ( InvalidMacaroonError ):
75
- caveat (json .dumps (predicate ))
74
+
75
+ assert caveat (json .dumps (predicate )) is False
76
76
77
77
def test_verify_project_no_projects_object (self , db_request ):
78
78
project = ProjectFactory .create (name = "foobar" )
@@ -83,8 +83,8 @@ def test_verify_project_no_projects_object(self, db_request):
83
83
"version" : 1 ,
84
84
"permissions" : {"somethingthatisntprojects" : ["blah" ]},
85
85
}
86
- with pytest . raises ( InvalidMacaroonError ):
87
- caveat (json .dumps (predicate ))
86
+
87
+ assert caveat (json .dumps (predicate )) is False
88
88
89
89
def test_verify_project (self , db_request ):
90
90
project = ProjectFactory .create (name = "foobar" )
@@ -95,6 +95,56 @@ def test_verify_project(self, db_request):
95
95
assert caveat (json .dumps (predicate )) is True
96
96
97
97
98
+ class TestExpiryCaveat :
99
+ @pytest .mark .parametrize (
100
+ "predicate" ,
101
+ [
102
+ # invalid JSON
103
+ "invalid json" ,
104
+ # missing nbf and exp
105
+ '{"missing": "values"}' ,
106
+ # nbf and exp present, but null
107
+ '{"nbf": null, "exp": null}' ,
108
+ # nbf and exp present, but empty
109
+ '{"nbf": "", "exp": ""}' ,
110
+ # valid JSON, but wrong type
111
+ "[]" ,
112
+ ],
113
+ )
114
+ def test_verify_invalid_predicates (self , predicate ):
115
+ verifier = pretend .stub ()
116
+ caveat = ExpiryCaveat (verifier )
117
+
118
+ assert caveat (predicate ) is False
119
+
120
+ def test_verify_not_before (self ):
121
+ verifier = pretend .stub ()
122
+ caveat = ExpiryCaveat (verifier )
123
+
124
+ not_before = int (time .time ()) + 60
125
+ expiry = not_before + 60
126
+ predicate = json .dumps ({"exp" : expiry , "nbf" : not_before })
127
+ assert caveat (predicate ) is False
128
+
129
+ def test_verify_already_expired (self ):
130
+ verifier = pretend .stub ()
131
+ caveat = ExpiryCaveat (verifier )
132
+
133
+ not_before = int (time .time ()) - 10
134
+ expiry = not_before - 5
135
+ predicate = json .dumps ({"exp" : expiry , "nbf" : not_before })
136
+ assert caveat (predicate ) is False
137
+
138
+ def test_verify_ok (self ):
139
+ verifier = pretend .stub ()
140
+ caveat = ExpiryCaveat (verifier )
141
+
142
+ not_before = int (time .time ()) - 10
143
+ expiry = int (time .time ()) + 60
144
+ predicate = json .dumps ({"exp" : expiry , "nbf" : not_before })
145
+ assert caveat (predicate )
146
+
147
+
98
148
class TestVerifier :
99
149
def test_creation (self ):
100
150
macaroon = pretend .stub ()
@@ -108,7 +158,7 @@ def test_creation(self):
108
158
assert verifier .principals is principals
109
159
assert verifier .permission is permission
110
160
111
- def test_verify (self , monkeypatch ):
161
+ def test_verify_invalid_signature (self , monkeypatch ):
112
162
verify = pretend .call_recorder (
113
163
pretend .raiser (MacaroonInvalidSignatureException )
114
164
)
@@ -120,6 +170,53 @@ def test_verify(self, monkeypatch):
120
170
verifier = Verifier (macaroon , context , principals , permission )
121
171
122
172
monkeypatch .setattr (verifier .verifier , "verify" , verify )
123
- with pytest .raises (InvalidMacaroonError ):
124
- verifier .verify (key )
173
+ assert verifier .verify (key ) is False
125
174
assert verify .calls == [pretend .call (macaroon , key )]
175
+
176
+ @pytest .mark .parametrize (
177
+ ["caveats" , "valid" ],
178
+ [
179
+ # Both V1 and expiry present and valid.
180
+ (
181
+ [
182
+ {"permissions" : "user" , "version" : 1 },
183
+ {"exp" : int (time .time ()) + 3600 , "nbf" : int (time .time ()) - 1 },
184
+ ],
185
+ True ,
186
+ ),
187
+ # V1 only present and valid.
188
+ ([{"permissions" : "user" , "version" : 1 }], True ),
189
+ # V1 and expiry present but V1 invalid.
190
+ ([{"permissions" : "bad" , "version" : 1 }], False ),
191
+ # V1 and expiry present but expiry invalid.
192
+ (
193
+ [
194
+ {"permissions" : "user" , "version" : 1 },
195
+ {"exp" : int (time .time ()) + 1 , "nbf" : int (time .time ()) + 3600 },
196
+ ],
197
+ False ,
198
+ ),
199
+ ],
200
+ )
201
+ def test_verify (self , monkeypatch , caveats , valid ):
202
+ key = os .urandom (32 )
203
+ m = pymacaroons .Macaroon (
204
+ location = "fakelocation" ,
205
+ identifier = "fakeid" ,
206
+ key = key ,
207
+ version = pymacaroons .MACAROON_V2 ,
208
+ )
209
+
210
+ for caveat in caveats :
211
+ m .add_first_party_caveat (json .dumps (caveat ))
212
+
213
+ # Round-trip through serialization to ensure we're not clinging to any state.
214
+ serialized_macaroon = m .serialize ()
215
+ deserialized_macaroon = pymacaroons .Macaroon .deserialize (serialized_macaroon )
216
+
217
+ context = pretend .stub ()
218
+ principals = pretend .stub ()
219
+ permission = pretend .stub ()
220
+
221
+ verifier = Verifier (deserialized_macaroon , context , principals , permission )
222
+ assert verifier .verify (key ) is valid
0 commit comments