sadpandajoe commented on code in PR #45870:
URL: https://github.com/apache/superset/pull/45870#discussion_r4419548127


##########
tests/unit_tests/databases/commands/importers/v1/import_test.py:
##########
@@ -970,3 +975,172 @@ def 
test_import_database_masked_encrypted_extra_not_revealed_on_host_change(
     assert database.password == "newpass"  # noqa: S105
     encrypted = json.loads(database.encrypted_extra)
     assert encrypted["my_secret"] == PASSWORD_MASK
+
+
+def test_import_database_never_stores_a_mask_over_an_existing_db(
+    mocker: MockerFixture,
+    session: Session,
+) -> None:
+    """
+    Overwriting a connection that has no stored value for a masked secret 
fails.
+
+    A connection promoted by a dashboard bundle exists without its secrets, so
+    there is nothing to reveal; storing the mask would make it the secret (QA
+    OEF-SECRET-04). The schema asks for the value first; this is the backstop.
+    """
+    from superset import security_manager
+    from superset.commands.database.importers.v1.utils import import_database
+    from superset.commands.exceptions import ImportFailedError
+    from superset.constants import PASSWORD_MASK
+    from superset.models.core import Database
+    from tests.integration_tests.fixtures.importexport import (
+        database_config_with_masked_encrypted_extra,
+    )
+
+    mocker.patch.object(security_manager, "can_access", return_value=True)
+    
mocker.patch("superset.commands.database.importers.v1.utils.add_permissions")
+
+    engine = db.session.get_bind()
+    Database.metadata.create_all(engine)  # pylint: disable=no-member
+
+    # The promoted copy: same connection, no encrypted_extra.
+    config = copy.deepcopy(database_config_with_masked_encrypted_extra)
+    del config["masked_encrypted_extra"]
+    existing = import_database(config)
+    db.session.flush()
+
+    masked = copy.deepcopy(database_config_with_masked_encrypted_extra)
+    masked["masked_encrypted_extra"] = json.dumps(
+        {"credentials_info": {"type": "service_account", "private_key": 
PASSWORD_MASK}}
+    )
+    with pytest.raises(ImportFailedError, 
match="credentials_info.private_key"):
+        import_database(masked, overwrite=True)
+
+    assert existing.encrypted_extra is None
+
+
+EMBEDDED_KEYPAIR = {
+    "username": "EMBED_SVC",
+    "auth_method": "keypair",
+    "privatekey_body": "-----BEGIN PRIVATE KEY-----\nKEY\n-----END PRIVATE 
KEY-----\n",
+    "privatekey_pass": "passphrase",
+}
+
+
+def _snowflake_config(embedded_credentials: dict[str, str]) -> dict[str, 
object]:
+    """A per-user OAuth2 Snowflake connection carrying an embedded 
credential."""
+    return {
+        "database_name": "imported_snowflake",
+        "sqlalchemy_uri": "snowflake://base_user@account/db?warehouse=WH",
+        "uuid": "6c1c5ee7-1d83-4f57-9a8e-1a2b3c4d5e6f",
+        "version": "1.0.0",
+        "extra": {},
+        "impersonate_user": True,
+        "masked_encrypted_extra": json.dumps(

Review Comment:
   Every new command test builds its config through `masked_encrypted_extra`, 
but this commit also moved the completeness check out of that branch so it now 
runs for a bundle that supplies only `encrypted_extra`. If the check were moved 
back inside the `masked_encrypted_extra` block, all four of these tests would 
still pass while an overwrite carrying `{"embedded_credentials": {"username": 
"u"}}` in plain `encrypted_extra` would again replace the stored credential 
unchecked. Would it be worth adding one overwrite case that uses only 
`encrypted_extra` and asserts the `$.embedded_credentials.password` refusal and 
the unchanged stored credential?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to