feat: auto-detect ML-DSA keys in service account JSON credentials - #18131
feat: auto-detect ML-DSA keys in service account JSON credentials#18131ohmayr wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for post-quantum ML-DSA service account keys by detecting them in from_dict and returning a PqcSigner, accompanied by unit tests for both successful detection and upgrade scenarios. The feedback suggests type-validating the untrusted data input to prevent TypeError exceptions when checking for the private key, in line with the repository style guide. Additionally, it recommends mocking the entire crypt.pqc attribute in the unit tests to avoid potential AttributeError issues in environments where crypt.pqc is not present.
| if "private_key" in data and crypt.is_mldsa_key(data["private_key"]): | ||
| return crypt.PqcSigner.from_service_account_info(data) |
There was a problem hiding this comment.
According to the Repository Style Guide (Rule 2: Input Validation), any data loaded from external configuration files is untrusted and must be type-validated before indexing or calling dictionary lookup keys to avoid TypeError exceptions.
If data is not a dictionary, or if data["private_key"] is not a string, this check can raise a TypeError. We should explicitly verify that data is a dictionary and that data.get("private_key") is a string before passing it to crypt.is_mldsa_key.
| if "private_key" in data and crypt.is_mldsa_key(data["private_key"]): | |
| return crypt.PqcSigner.from_service_account_info(data) | |
| if ( | |
| isinstance(data, dict) | |
| and isinstance(data.get("private_key"), str) | |
| and crypt.is_mldsa_key(data["private_key"]) | |
| ): | |
| return crypt.PqcSigner.from_service_account_info(data) |
References
- Any data loaded from external configuration files (JSON, YAML, CSV) is untrusted. Always type-validate structure (e.g. check isinstance(data, dict) and isinstance(data.get("sub_key"), dict)) before indexing or calling dictionary lookup keys, avoiding TypeError exceptions. (link)
|
|
||
|
|
||
| def test_from_dict_mldsa_signer_auto_detect_upgrade_required(monkeypatch): | ||
| monkeypatch.setattr(crypt.pqc, "mldsa", None) |
There was a problem hiding this comment.
If the environment running the tests has an older version of cryptography where crypt.pqc is None or does not exist, attempting to set an attribute on crypt.pqc directly will raise an AttributeError.
To make the test robust across all environments, mock the pqc attribute on the crypt module instead.
mock_pqc = mock.Mock()
mock_pqc.mldsa = None
monkeypatch.setattr(crypt, "pqc", mock_pqc)| monkeypatch.setattr(crypt.pqc, "mldsa", mock_mldsa) | ||
| monkeypatch.setattr( | ||
| crypt.pqc.serialization, | ||
| "load_pem_private_key", | ||
| lambda key, password, backend: MockMLDSA65PrivateKey(), | ||
| ) |
There was a problem hiding this comment.
Similarly to the previous test, directly setting attributes on crypt.pqc or crypt.pqc.serialization can raise an AttributeError if they are not present or are None in the current environment.
We should mock the entire pqc attribute on the crypt module to ensure the test is robust.
mock_pqc = mock.Mock()
mock_pqc.mldsa = mock_mldsa
mock_pqc.serialization.load_pem_private_key = lambda key, password, backend: MockMLDSA65PrivateKey()
monkeypatch.setattr(crypt, "pqc", mock_pqc)cc3754d to
a8ade66
Compare
a8ade66 to
8bd2f74
Compare
8bd2f74 to
7128113
Compare
7128113 to
1f0aae2
Compare
WIP