Merge lp:~facundo/canonical-identity-provider/remove-refresh-with-both-macaroons into lp:canonical-identity-provider/release

Proposed by Facundo Batista
Status: Merged
Approved by: Facundo Batista
Approved revision: no longer in the source branch.
Merge reported by: Ubuntu One Auto Pilot
Merged at revision: not available
Proposed branch: lp:~facundo/canonical-identity-provider/remove-refresh-with-both-macaroons
Merge into: lp:canonical-identity-provider/release
Diff against target: 256 lines (+2/-192)
4 files modified
src/api/v20/handlers.py (+1/-12)
src/api/v20/tests/test_handlers.py (+0/-18)
src/identityprovider/auth.py (+0/-31)
src/identityprovider/tests/test_auth.py (+1/-131)
To merge this branch: bzr merge lp:~facundo/canonical-identity-provider/remove-refresh-with-both-macaroons
Reviewer Review Type Date Requested Status
Matias Bordese (community) Approve
Review via email: mp+302731@code.launchpad.net

Commit message

Removed the deprecated way of refreshing macaroons (sending both root and discharge).

Description of the change

Removed the deprecated way of refreshing macaroons (sending both root and discharge).

To post a comment you must log in.
Revision history for this message
Matias Bordese (matiasb) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/api/v20/handlers.py'
2--- src/api/v20/handlers.py 2016-07-27 14:41:55 +0000
3+++ src/api/v20/handlers.py 2016-08-11 22:17:29 +0000
4@@ -556,19 +556,8 @@
5 missing = {'discharge_macaroon': [FIELD_REQUIRED]}
6 return errors.INVALID_DATA(**missing)
7
8- if 'root_macaroon' in data:
9- # (deprecated 2016-05-03) use the root macaroon to old-fashion
10- # refresh, that also returns a bound discharge
11- method = auth.refresh_macaroons
12- params = (data['root_macaroon'], discharge_macaroon_raw)
13- stats.increment('macaroon.refresh', key='root_macaroon')
14- else:
15- method = auth.refresh_discharge
16- params = (discharge_macaroon_raw,)
17- stats.increment('macaroon.refresh', key='just_discharge')
18-
19 try:
20- new_discharge = method(*params)
21+ new_discharge = auth.refresh_discharge(discharge_macaroon_raw)
22 except ValidationError:
23 return errors.INVALID_DATA()
24 except AccountDeactivated:
25
26=== modified file 'src/api/v20/tests/test_handlers.py'
27--- src/api/v20/tests/test_handlers.py 2016-08-08 16:57:28 +0000
28+++ src/api/v20/tests/test_handlers.py 2016-08-11 22:17:29 +0000
29@@ -2850,22 +2850,6 @@
30 expected_status_code=401,
31 check_login_failed=False)
32
33- def test_macaroon_refreshed(self):
34- data = {'root_macaroon': self.root_macaroon.serialize(),
35- 'discharge_macaroon': self.discharge_macaroon.serialize()}
36- json_body = self.do_post(data=data)
37-
38- # get new discharge macaroon and verify with old root (its internals
39- # are verified by the tests of the 'refresh_macaroons' function itself)
40- discharge_macaroon_raw = json_body['discharge_macaroon']
41- discharge_macaroon = Macaroon.deserialize(discharge_macaroon_raw)
42- v = Verifier()
43- v.satisfy_general(lambda c: True)
44- v.verify(
45- self.root_macaroon, self.macaroon_random_key, [discharge_macaroon])
46- self.stats_increment.assert_any_call(
47- 'macaroon.refresh', key='root_macaroon')
48-
49 def test_just_discharge_refreshed(self):
50 json_body = self.do_post()
51
52@@ -2878,5 +2862,3 @@
53 v = Verifier()
54 v.satisfy_general(lambda c: True)
55 v.verify(self.root_macaroon, self.macaroon_random_key, [discharge])
56- self.stats_increment.assert_any_call(
57- 'macaroon.refresh', key='just_discharge')
58
59=== modified file 'src/identityprovider/auth.py'
60--- src/identityprovider/auth.py 2016-07-28 16:07:45 +0000
61+++ src/identityprovider/auth.py 2016-08-11 22:17:29 +0000
62@@ -667,37 +667,6 @@
63 return account, info_holder
64
65
66-def refresh_macaroons(root_macaroon_raw, discharge_macaroon_raw):
67- """Refresh a root/discharge pair with a new discharge macaroon.
68-
69- This function is deprecated; will be removed when clients stop hitting
70- the handler passing the root macaroon.
71- """
72- try:
73- root_macaroon = Macaroon.deserialize(root_macaroon_raw)
74- discharge_macaroon = Macaroon.deserialize(discharge_macaroon_raw)
75- except:
76- raise ValidationError("The received Macaroons are corrupt")
77-
78- # get the raw caveat id and the decrypted deserialized info
79- raw_caveat_id, caveat_info = _get_own_caveat(root_macaroon)
80-
81- account, macaroon_info = _account_from_macaroon(
82- root_macaroon, caveat_info['roothash'], discharge_macaroon)
83-
84- # create the new discharge macaroon with same location, key and
85- # identifier than it's original 3rd-party caveat (so they can
86- # be matched and verified), and keeping the last_auth and expires from
87- # the original discharge macaroon
88- d = _build_discharge(
89- caveat_info['3rdparty'], raw_caveat_id, account,
90- last_auth=macaroon_info['last_auth'], expires=macaroon_info['expires'])
91-
92- # return the properly prepared discharge macaroon
93- discharge = root_macaroon.prepare_for_request(d)
94- return discharge
95-
96-
97 def refresh_discharge(discharge_macaroon_raw):
98 """Refresh a discharge with a new discharge macaroon."""
99 try:
100
101=== modified file 'src/identityprovider/tests/test_auth.py'
102--- src/identityprovider/tests/test_auth.py 2016-08-01 14:17:32 +0000
103+++ src/identityprovider/tests/test_auth.py 2016-08-11 22:17:29 +0000
104@@ -34,7 +34,6 @@
105 build_discharge_macaroon,
106 build_discharge_macaroon_from_root,
107 refresh_discharge,
108- refresh_macaroons,
109 validate_oauth_signature,
110 )
111 from identityprovider.login import AuthenticationError, AccountDeactivated
112@@ -1175,135 +1174,6 @@
113 self.assertRaises(ValidationError, _decrypt_caveat, caveat_id)
114
115
116-class MacaroonRefreshFromRootTestCase(SSOBaseTestCase):
117- """Test the deprecated refresh_macaroons.
118-
119- These tests are kept separated as that function won't evolve no more.
120- """
121-
122- def setUp(self):
123- super(MacaroonRefreshFromRootTestCase, self).setUp()
124- self.root_macaroon, self.macaroon_random_key, _ = self.build_macaroon(
125- version=0)
126-
127- # discharge the test macaroon
128- self.account = self.factory.make_account()
129- self.discharge_macaroon = build_discharge_macaroon_from_root(
130- self.account, self.root_macaroon.serialize())
131-
132- def test_root_macaroon_corrupt(self):
133- self.assertRaises(
134- ValidationError, refresh_macaroons,
135- "Corrupted macaroon", self.discharge_macaroon.serialize())
136-
137- def test_discharge_macaroon_corrupt(self):
138- self.assertRaises(
139- ValidationError, refresh_macaroons,
140- self.root_macaroon.serialize(), "Seriously corrupted macaroon")
141-
142- def test_macaroons_dont_verify_ok(self):
143- # just get *another* discharge so it's not for the same root macaroon
144- other_root, _, _ = self.build_macaroon(version=0)
145- other_discharge = build_discharge_macaroon_from_root(
146- self.account, other_root.serialize())
147- self.assertRaises(AuthenticationError, refresh_macaroons,
148- self.root_macaroon.serialize(),
149- other_discharge.serialize())
150-
151- def test_deactivated_account(self):
152- self.account.deactivate()
153- self.assertRaises(AccountDeactivated, refresh_macaroons,
154- self.root_macaroon.serialize(),
155- self.discharge_macaroon.serialize())
156-
157- def test_password_changed(self):
158- self.account.set_password("a new password")
159- self.assertRaises(AuthenticationError, refresh_macaroons,
160- self.root_macaroon.serialize(),
161- self.discharge_macaroon.serialize())
162-
163- def test_password_with_no_datetime(self):
164- # simulate an "old" account password (before we started to keep the
165- # changed date); note that I'm bypassing the AccountPassword save(),
166- # which will update the attribute that I want in Null! (and we confirm
167- # that in the assert)
168- self.account.accountpassword.date_changed = None
169- super(AccountPassword, self.account.accountpassword).save()
170- assert self.account.accountpassword.date_changed is None
171-
172- # check that auths ok
173- refresh_macaroons(self.root_macaroon.serialize(),
174- self.discharge_macaroon.serialize())
175-
176- def test_proper_refreshing(self):
177- old_discharge = self.discharge_macaroon # just rename for readability
178- service_location = settings.MACAROON_SERVICE_LOCATION
179-
180- def get_value(search_key):
181- for caveat in old_discharge.first_party_caveats():
182- source, key, value = caveat.caveat_id.split("|", 2)
183- if source == service_location and key == search_key:
184- return value
185-
186- # get old values from the macaroon and also change the account to see
187- # that reflected
188- old_last_auth = get_value('last_auth')
189- old_expires = get_value('expires')
190- new_mail = self.factory.make_email_for_account(
191- self.account, status=EmailStatus.PREFERRED)
192- self.account.displayname = "New test display name"
193- self.account.save()
194-
195- # call!
196- before = now()
197- new_discharge = refresh_macaroons(self.root_macaroon.serialize(),
198- old_discharge.serialize())
199- after = now()
200-
201- # test
202- def checker(caveat):
203- """Assure all caveats inside the discharged macaroon are ok."""
204- source, key, value = caveat.split("|", 2)
205- if source != service_location:
206- # just checking the NEW discharge one, not the root
207- return True
208-
209- if key == 'valid_since':
210- valid_since = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f')
211- self.assertGreater(valid_since, before)
212- self.assertGreater(after, valid_since)
213- return True
214-
215- if key == 'last_auth':
216- self.assertEqual(value, old_last_auth)
217- return True
218-
219- if key == 'account':
220- expected = {
221- 'openid': self.account.openid_identifier,
222- 'email': new_mail.email,
223- 'displayname': "New test display name",
224- 'is_verified': self.account.is_verified,
225- 'username': self.account.username
226- }
227- actual = json.loads(base64.b64decode(value).decode("utf8"))
228- self.assertEqual(expected, actual)
229- return True
230-
231- if key == 'expires':
232- self.assertEqual(value, old_expires)
233- return True
234-
235- # we're not validating an SSO from the discharged macaroon, fail!
236- return False
237-
238- # verify using the NEW discharge macaroon
239- v = Verifier()
240- v.satisfy_general(checker)
241- v.verify(self.root_macaroon, self.macaroon_random_key,
242- [new_discharge])
243-
244-
245 class MacaroonRefreshTestCase(SSOBaseTestCase):
246
247 def setUp(self):
248@@ -1386,7 +1256,7 @@
249 expected = {
250 'openid': self.account.openid_identifier,
251 'email': new_mail.email,
252- 'displayname': "New test display name",
253+ 'displayname': "New test display name",
254 'is_verified': self.account.is_verified,
255 'username': self.account.username
256 }