Skip to content

Commit

Permalink
Canonical json form for signed responses (#3035)
Browse files Browse the repository at this point in the history
* Add canonicaljson dependency to requirements

* Modify responses to use canonical json form

* Update requirements to include canonicaljson in base.txt

* Add tests for canonical json

* Stop setting json format as canonicaljson currently uses json under the hood

* Update test to compare JSON string with expected canonical order

* Remove response assertion in test

* Update requirements after resolving merge conflicts

* Fix format errors

* Fix import sorting
  • Loading branch information
michellemounde committed Nov 15, 2023
1 parent 290c5fb commit 8fa6999
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 10 deletions.
1 change: 1 addition & 0 deletions requirements/base.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
aiohttp
arrow
auth0-python
canonicaljson
connexion<3
deepmerge
ecdsa
Expand Down
12 changes: 8 additions & 4 deletions requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# SHA1:ef18935427a28f552caa0a5d204b56df45dd5a59
# SHA1:d8d01e1e74eb36df6eb89f0f209b27e3f195c07c
#
# This file is autogenerated by pip-compile-multi
# To update, run:
Expand Down Expand Up @@ -220,6 +220,10 @@ cachetools==5.3.2 \
--hash=sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2 \
--hash=sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1
# via google-auth
canonicaljson==2.0.0 \
--hash=sha256:c38a315de3b5a0532f1ec1f9153cd3d716abfc565a558d00a4835428a34fca5b \
--hash=sha256:e2fdaef1d7fadc5d9cb59bd3d0d41b064ddda697809ac4325dced721d12f113f
# via -r requirements/base.in
certifi==2023.7.22 \
--hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \
--hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9
Expand Down Expand Up @@ -718,9 +722,9 @@ jsonschema==4.19.2 \
# -r requirements/base.in
# connexion
# swagger-spec-validator
jsonschema-specifications==2023.7.1 \
--hash=sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1 \
--hash=sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb
jsonschema-specifications==2023.11.1 \
--hash=sha256:c9b234904ffe02f079bf91b14d79987faa685fd4b39c377a0996954c0090b9ca \
--hash=sha256:f596778ab612b3fd29f72ea0d990393d0540a5aab18bf0407a46632eab540779
# via jsonschema
markupsafe==2.1.3 \
--hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \
Expand Down
6 changes: 3 additions & 3 deletions requirements/docs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -635,9 +635,9 @@ jsonschema==4.19.2 \
# -r requirements/docs.in
# connexion
# swagger-spec-validator
jsonschema-specifications==2023.7.1 \
--hash=sha256:05adf340b659828a004220a9613be00fa3f223f2b82002e273dee62fd50524b1 \
--hash=sha256:c91a50404e88a1f6ba40636778e2ee08f6e24c5613fe4c53ac24578a5a7f72bb
jsonschema-specifications==2023.11.1 \
--hash=sha256:c9b234904ffe02f079bf91b14d79987faa685fd4b39c377a0996954c0090b9ca \
--hash=sha256:f596778ab612b3fd29f72ea0d990393d0540a5aab18bf0407a46632eab540779
# via jsonschema
markupsafe==2.1.3 \
--hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \
Expand Down
5 changes: 2 additions & 3 deletions src/auslib/web/public/json.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import json

import canonicaljson
from flask import Response
from flask import current_app as app

Expand All @@ -17,7 +16,7 @@ def get_update(transaction, **parameters):

headers = get_aus_metadata_headers(eval_metadata)

response = json.dumps(release.getResponse(parameters, app.config["ALLOWLISTED_DOMAINS"]))
response = canonicaljson.encode_canonical_json(release.getResponse(parameters, app.config["ALLOWLISTED_DOMAINS"]))

headers.update(get_content_signature_headers(response, ""))

Expand Down
42 changes: 42 additions & 0 deletions tests/web/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,48 @@ def testGuardianResponse(client, version, buildTarget, channel, code, response):
assert "Rule-Data-Version" in ret.headers


@pytest.mark.usefixtures("appconfig", "guardian_db", "disable_errorhandler", "mock_autograph")
@pytest.mark.parametrize(
"version,buildTarget,channel,code,jsonString",
[
(
"0.4.0.0",
"WINNT_x86_64",
"release",
200,
'{"hashFunction":"sha512","hashValue":"abcdef","required":true,"url":"https://good.com/0.5.0.0.msi","version":"0.5.0.0"}',
),
(
"0.6.0.0",
"WINNT_x86_64",
"release",
200,
'{"hashFunction":"sha512","hashValue":"mnopqr","required":true,"url":"https://good.com/1.0.0.0.msi","version":"1.0.0.0"}',
),
(
"0.99.99.99",
"WINNT_x86_64",
"release",
200,
'{"hashFunction":"sha512","hashValue":"mnopqr","required":true,"url":"https://good.com/1.0.0.0.msi","version":"1.0.0.0"}',
),
("1.0.0.0", "WINNT_x86_64", "release", 404, "{}"),
("0.6.0.0", "Linux_x86_64", "release", 404, "{}"),
("0.6.0.0", "WINNT_x86_64", "beta", 404, "{}"),
# This shouldn't match because the rule on the alpha channel contains fields not used by this type of update query.
("0.6.0.0", "WINNT_x86_64", "alpha", 404, "{}"),
("0.6.0.0", "Darwin_x86_64", "evilrelease", 200, "{}"),
],
)
def testGuardianResponseWithCanonicalJson(client, version, buildTarget, channel, code, jsonString):
ret = client.get(f"/json/1/Guardian/{version}/{buildTarget}/{channel}/update.json")
assert ret.status_code == code
if code == 200:
assert ret.mimetype == "application/json"
assert ret.text == jsonString
assert ret.headers["Content-Signature"] == "x5u=https://this.is/a.x5u; p384ecdsa=abcdef"


@pytest.mark.usefixtures("appconfig", "guardian_db", "disable_errorhandler")
@pytest.mark.parametrize(
"version,buildTarget,channel,code,response",
Expand Down

0 comments on commit 8fa6999

Please sign in to comment.