-
Notifications
You must be signed in to change notification settings - Fork 20
Description
Bug Report: AttributeError in aws-cryptographic-material-providers
Summary
The AWS Cryptographic Material Providers library crashes with an AttributeError when deserializing KMS errors, preventing proper error handling and masking the underlying AWS KMS permission issue.
Error Details
- Exception Type:
AttributeError - Exception Message:
'Error_OpaqueWithText' object has no attribute 'message' - Library:
aws-cryptographic-material-providers - File:
smithygenerated/aws_cryptography_materialproviders/deserialize.py - Line: 375
Root Cause
The code at line 375 attempts to access .message attribute on error.ComAmazonawsKms, but when the KMS error is an Error_OpaqueWithText type, it has .objMessage instead of .message.
Source Location:
Line 375 in 515995e
| return ComAmazonawsKms(message=_dafny.string_of(error.ComAmazonawsKms.message)) |
Problematic Code (Line 375)
elif error.is_ComAmazonawsKms:
return ComAmazonawsKms(message=_dafny.string_of(error.ComAmazonawsKms.message))Actual Error Structure
Error_ComAmazonawsKms(
ComAmazonawsKms=Error_OpaqueWithText(
obj=ClientError(...),
objMessage=<_dafny.Seq object> # Note: objMessage, not message
)
)Stack Trace
/usr/local/lib/python3.11/site-packages/aws_encryption_sdk/__init__.py:218 in decrypt
│ 215 │ │ self._set_config_kwargs("decrypt", kwargs)
│ 216 │ │ kwargs["signature_policy"] = SignaturePolicy.ALLOW_ENCRYPT_ALL
│ 217 │ │ with StreamDecryptor(**kwargs) as decryptor:
│ ❱ 218 │ │ │ plaintext = decryptor.read()
│ 219 │ │ return plaintext, decryptor.header
/usr/local/lib/python3.11/site-packages/aws_encryption_sdk/streaming_client.py:342 in read
│ 339 │ │ output = io.BytesIO()
│ 340 │ │
│ 341 │ │ if not self._message_prepped:
│ ❱ 342 │ │ │ self._prep_message()
│ 343 │ │
/usr/local/lib/python3.11/site-packages/aws_encryption_sdk/streaming_client.py:941 in _prep_message
│ 938 │
│ 939 │ def _prep_message(self):
│ 940 │ │ """Performs initial message setup."""
│ ❱ 941 │ │ self._header, self.header_auth = self._read_header()
/usr/local/lib/python3.11/site-packages/aws_encryption_sdk/streaming_client.py:1045 in _read_header
│ 1042 │ │ │ )
│ 1043 │ │
│ 1044 │ │ decrypt_materials_request = self._create_decrypt_materials_request(...)
│ ❱ 1045 │ │ decryption_materials = self.config.materials_manager.decrypt_materials(...)
/usr/local/lib/python3.11/site-packages/aws_encryption_sdk/materials_managers/mpl/cmm.py:124 in decrypt_materials
│ 121 │ │ try:
│ 122 │ │ │ mpl_input: 'MPL_DecryptMaterialsInput' = \
│ 123 │ │ │ │ CryptoMaterialsManagerFromMPL._create_mpl_decrypt_materials_input(...)
│ ❱ 124 │ │ │ mpl_output: 'MPL_DecryptMaterialsOutput' = self.mpl_cmm.decrypt_materials(...)
/usr/local/lib/python3.11/site-packages/aws_cryptographic_material_providers/smithygenerated/aws_cryptography_materialproviders/references.py:566 in decrypt_materials
│ 563 │ │ │ │ _deserialize_error as aws_cryptography_materialproviders_deserialize_error
│ 564 │ │ │ )
│ 565 │ │ │
│ ❱ 566 │ │ │ raise aws_cryptography_materialproviders_deserialize_error(
│ 567 │ │ │ │ dafny_output.error
│ 568 │ │ │ )
/usr/local/lib/python3.11/site-packages/aws_cryptographic_material_providers/smithygenerated/aws_cryptography_materialproviders/deserialize.py:330 in _deserialize_error
│ 327 │ elif error.is_CollectionOfErrors:
│ 328 │ │ return CollectionOfErrors(
│ 329 │ │ │ message=_dafny.string_of(error.message),
│ ❱ 330 │ │ │ list=[_deserialize_error(dafny_e) for dafny_e in error.list],
│ 331 │ │ )
/usr/local/lib/python3.11/site-packages/aws_cryptographic_material_providers/smithygenerated/aws_cryptography_materialproviders/deserialize.py:330 in <listcomp>
│ 327 │ elif error.is_CollectionOfErrors:
│ 328 │ │ return CollectionOfErrors(
│ 329 │ │ │ message=_dafny.string_of(error.message),
│ ❱ 330 │ │ │ list=[_deserialize_error(dafny_e) for dafny_e in error.list],
│ 331 │ │ )
╭───────────────────────────────── locals ─────────────────────────────────╮
│ .0 = <iterator object at 0x...> │
│ dafny_e = Error_ComAmazonawsKms( │
│ │ ComAmazonawsKms=Error_OpaqueWithText( │
│ │ │ obj=ClientError('An error occurred │
│ (AccessDeniedException) when calling the Decrypt operation: │
│ User: arn:aws:iam::<ACCOUNT_ID>:user/<USERNAME> is │
│ not authorized to perform: kms:Decrypt on the resource │
│ associated with this ciphertext because the resource does not │
│ exist in this Region, no resource-based policies allow access, │
│ or a resource-based policy explicitly denies access'), │
│ │ │ objMessage=<_dafny.Seq object at 0x...> │
│ │ ), │
│ ) │
╰──────────────────────────────────────────────────────────────────────────╯
/usr/local/lib/python3.11/site-packages/aws_cryptographic_material_providers/smithygenerated/aws_cryptography_materialproviders/deserialize.py:375 in _deserialize_error
│ 372 │ │ │ aws_cryptography_keystore_deserialize_error(error.AwsCryptographyKeyStore)
│ 373 │ │ )
│ 374 │ elif error.is_ComAmazonawsKms:
│ ❱ 375 │ │ return ComAmazonawsKms(message=_dafny.string_of(error.ComAmazonawsKms.message))
│ 376 │ elif error.is_ComAmazonawsDynamodb:
│ 377 │ │ return ComAmazonawsDynamodb(
│ 378 │ │ │ message=_dafny.string_of(error.ComAmazonawsDynamodb.message)
Expected Behavior
When a KMS decryption error occurs (e.g., AccessDeniedException), the library should properly deserialize and propagate the error with a clear message about the underlying AWS KMS issue.
Actual Behavior
The error deserialization crashes with AttributeError, masking the actual KMS permission error and making debugging difficult.
Proposed Fix
The code should recursively deserialize nested errors, similar to how other error types are handled (lines 364-372):
elif error.is_ComAmazonawsKms:
return ComAmazonawsKms(_deserialize_error(error.ComAmazonawsKms))
elif error.is_ComAmazonawsDynamodb:
return ComAmazonawsDynamodb(_deserialize_error(error.ComAmazonawsDynamodb))This would properly handle cases where the nested error is an Error_OpaqueWithText or any other error type.
Environment
- Python: 3.11
- aws-encryption-sdk==4.0.3
- aws-cryptographic-material-providers==1.11.1
Reproducibility
This occurs when:
- Attempting to decrypt data encrypted with AWS KMS
- The KMS service returns an error (e.g.,
AccessDeniedException) - The error is wrapped as
Error_OpaqueWithTextinstead of having a direct.messageattribute
Impact
Severity: Medium-High
This bug prevents proper error handling and makes debugging KMS permission issues extremely difficult, as the original KMS error message is lost in the secondary AttributeError.
Notes
This appears to be machine-generated code (file header indicates "This file is machine generated, and any changes to it will be overwritten"). The fix should be applied to the code generation template.