Skip to content

Commit 6802295

Browse files
Allow none body put post patch requests (#232)
Allow none body put post patch requests update request example in this doc to not encode body if none on post put or patch: https://strateos.atlassian.net/wiki/spaces/ENG/pages/1823801375/Onboarding+Request+Signing+Authentication+RSA+for+Strateos+Console+User
1 parent a929fe6 commit 6802295

4 files changed

Lines changed: 95 additions & 2 deletions

File tree

CHANGELOG.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Changelog
22
=========
33

4+
v9.6.3
5+
----------
6+
7+
Fixed
8+
-----
9+
- Allow empty body in put post patch requests with rsa requests
10+
411
v9.6.2
512
----------
613

test/config_test.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,92 @@ def test_signing(self):
186186
{"(request-target)", "date", "host", "content-length", "digest"},
187187
)
188188

189+
def test_signing_post_no_body_in_request(self):
190+
# Set up a connection with a key from a file
191+
with tempfile.NamedTemporaryFile() as config_file, tempfile.NamedTemporaryFile() as key_file:
192+
with open(key_file.name, "w") as kf:
193+
kf.write(
194+
"-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQDIK/IzSkBEuwKjYQo/ri4iKTTkr+FDtJetI7dYoz0//U5z7Vbu\nZQWncDNc38wMKidf2bWA+MTSWcYVUTlivp0y98MTLPsR6oJ9RwLggA2lFlCIjmdV\nUow/MmhWg0vX/SkThxS/F5I41GTrNIU3ZVZwGbmQ8hbyKCBYtbEHJWqATwIDAQAB\nAoGAHtYmSaB2ph/pGCIq4gSDNuACNfiiSzvW4eVOqWj8Vo8/NrypV7BYXqL6RqRz\nWqxjxHBVdbjdGUqbKU2J+ZxDuwCREsxQipjq+hM9aPpgjNJg4dz6yuc5mnUdOr9M\nR+zFjnnOJx98HGjuzLDXdBNYVSZFcDWj70Fjln/z5AjBYQECQQDijaHEcvDJOUmL\nDNyAYbjK811kFGpmglQBiZ257L47IP6jgqN544siHGnI7rykt+1upGfB2q8uQSIb\njNJKKsa3AkEA4jB9PXE8EooJ/eax2UsuwXt9LAgRabFurAJtadpAeeFBIIMSwBXU\n7APMfB3cQOnBlodnyrQ56mIOWPcSdN+7KQJAHr+4aBBtq/IRkETjnK0mxqz3TQEU\nW+tueXLzLGv8ecwFo620gHOoy61tki8M/ZJVMIIx7va+dhmzBmg7loNtywJAZUdy\n/K0USfTXToIaxoJcmDQUM0AVk+7n8EtR9KDOWASdpdIq9imQYnG9ASJZuhMxJJbS\nybfzatinNfzDneOEKQJBAMLOhHHbskUuuU9oDUl8sbrsreglQuoq1hvlB1uVskpi\nqMEIXSBwxAlxwmiAQLgS4hZY+cmQ3v5hCberMaZRPZ8=\n-----END RSA PRIVATE KEY-----\n"
195+
)
196+
with open(config_file.name, "w") as f:
197+
json.dump(
198+
{
199+
"email": "somebody@transcriptic.com",
200+
"token": "foobarinvalid",
201+
"organization_id": "transcriptic",
202+
"api_root": "http://foo:5555",
203+
"analytics": True,
204+
"user_id": "ufoo2",
205+
"feature_groups": [
206+
"can_submit_autoprotocol",
207+
"can_upload_packages",
208+
],
209+
"rsa_key": key_file.name,
210+
},
211+
f,
212+
)
213+
214+
connection = transcriptic.config.Connection.from_file(config_file.name)
215+
216+
# Test that GET signature matches the above key (given a hardcoded date header)
217+
get_request = requests.Request(
218+
"GET",
219+
"http://foo:5555/get",
220+
headers={
221+
"Date": formatdate(timeval=1588628873, localtime=False, usegmt=True)
222+
},
223+
)
224+
prepared_get = connection.session.prepare_request(get_request)
225+
self.assertTrue(
226+
prepared_get.headers["X-Organization-Id"] == connection.organization_id
227+
)
228+
self.assertTrue(
229+
prepared_get.headers["X-Organization-Id"] == connection.env_args["org_id"]
230+
)
231+
232+
get_sig = prepared_get.headers["authorization"]
233+
self.assertEqual(
234+
re.search(r'keyId="(.+?)"', get_sig).group(1), "somebody@transcriptic.com"
235+
)
236+
self.assertEqual(
237+
re.search(r'algorithm="(.+?)"', get_sig).group(1), "rsa-sha256"
238+
)
239+
self.assertEqual(
240+
re.search(r'signature="(.+?)"', get_sig).group(1),
241+
"GfcAtyV0+CKDkxjsREXYAm6RP0WdIYaN5RamlNfIYZ7e847KAydQf2ylYIcsj9CS5BIOiBi5JBoC6n51NSbxU+kQcSv2nzSsq3rBpTFFMHUhTPdrfeHsH4IBvgMWZZHmHvyE7UXVqhLssVzMIm/oGTnprPMWiTcsKjEhe+DsQT4=",
242+
)
243+
self.assertEqual(
244+
set(re.search(r'headers="(.+?)"', get_sig).group(1).split(" ")),
245+
{"(request-target)", "date", "host"},
246+
)
247+
248+
# Test that POST signature matches the above key (given a hardcoded body & date header)
249+
post_request = requests.Request(
250+
"POST",
251+
"http://foo:5555/get",
252+
data=None,
253+
headers={
254+
"Date": formatdate(timeval=1588638873, localtime=False, usegmt=True)
255+
},
256+
)
257+
prepared_post = connection.session.prepare_request(post_request)
258+
259+
post_sig = prepared_post.headers["authorization"]
260+
self.assertEqual(
261+
re.search(r'keyId="(.+?)"', post_sig).group(1), "somebody@transcriptic.com"
262+
)
263+
self.assertEqual(
264+
re.search(r'algorithm="(.+?)"', post_sig).group(1), "rsa-sha256"
265+
)
266+
self.assertEqual(
267+
re.search(r'signature="(.+?)"', post_sig).group(1),
268+
"leQ7TO8IYbOKouKjqbwvk5uYrkmmO64aWBxxWGDMA41Kn3k0/9r6L4XWLGmMIjSqzQmFHF8Sdtz7pCh8YaQLHzXzwY0+R43jlJGLiL7WzgzWegHsnY2NwGOdGPWbVqAP3oCmr2lQtzl+k39ySW3Tpd+t8c0+VDCYOOV/kIAISVw=",
269+
)
270+
self.assertEqual(
271+
set(re.search(r'headers="(.+?)"', post_sig).group(1).split(" ")),
272+
{"(request-target)", "date", "host", "content-length", "digest"},
273+
)
274+
189275
@responses.activate
190276
def test_signing_auth_header_on_redirects(self):
191277
# Set up a connection with a key from a file

transcriptic/auth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def __call__(self, request):
7575
if request.method.upper() in ("PUT", "POST", "PATCH"):
7676
encoded_body = (
7777
request.body
78-
if isinstance(request.body, bytes)
78+
if (isinstance(request.body, bytes) or request.body is None)
7979
else request.body.encode()
8080
)
8181
digest = SHA256.new(encoded_body).digest()

transcriptic/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "9.6.2"
1+
__version__ = "9.6.3"

0 commit comments

Comments
 (0)