Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/next-release/bugfix-cloudfront-sign.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"category": "cloudfront",
"description": "Raise a friendly error message when SHA1 signing is unavailable on the platform while running ``aws cloudfront sign``.",
"type": "bugfix"
}
20 changes: 16 additions & 4 deletions awscli/customizations/cloudfront.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from botocore.utils import parse_to_aware_datetime

from awscrt.crypto import RSA, RSASignatureAlgorithm
from awscrt.exceptions import AwsCrtError

from awscli.arguments import CustomArgument
from awscli.customizations.commands import BasicCommand
Expand Down Expand Up @@ -306,7 +307,18 @@ def __init__(self, private_key):
self.priv_key = RSA.new_private_key_from_pem_data(key_bytes)

def sign(self, message):
return self.priv_key.sign(
RSASignatureAlgorithm.PKCS1_5_SHA1,
hashlib.sha1(message).digest()
)
try:
return self.priv_key.sign(
RSASignatureAlgorithm.PKCS1_5_SHA1,
hashlib.sha1(message).digest()
)
except (AwsCrtError, RuntimeError) as e:
if 'AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM' in str(e):
raise RuntimeError(
"Failed to sign the URL using the SHA1 hash algorithm: "
f"{e} CloudFront signed URLs require RSA PKCS1 v1.5 "
"signing with SHA1, which may be disabled by default on "
"your platform. Enable SHA1 support in your system's "
"crypto provider and try again."
) from e
raise
37 changes: 37 additions & 0 deletions tests/functional/cloudfront/test_sign.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,43 @@ def test_custom_policy(self):
self.run_cmd(cmdline)[0], 'http://example.com/hi', expected_params
)

def test_raises_friendly_error_when_sha1_unavailable(self):
cmdline = (
self.prefix
+ '--private-key file://'
+ self.private_key_file
+ ' --date-less-than 2016-1-1'
)

crt_error = RuntimeError(
'7174 (AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM): The specified '
'algorithm is unsupported on this platform.'
)
with mock.patch(
'awscli.customizations.cloudfront.RSA.sign',
side_effect=crt_error,
):
stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=255)
self.assertNotEqual(rc, 0)
self.assertIn('SHA1', stderr)

def test_unrelated_signing_error_is_not_reported_as_sha1(self):
cmdline = (
self.prefix
+ '--private-key file://'
+ self.private_key_file
+ ' --date-less-than 2016-1-1'
)
other_error = RuntimeError('some other signing failure')
with mock.patch(
'awscli.customizations.cloudfront.RSA.sign',
side_effect=other_error,
):
stdout, stderr, rc = self.run_cmd(cmdline, expected_rc=255)
self.assertNotEqual(rc, 0)
self.assertNotIn('SHA1', stderr)
self.assertIn('some other signing failure', stderr)


class TestSignPKCS8(BaseAWSCommandParamsTest):
# A private key only for testing purpose.
Expand Down
Loading