)]}'
{"id":"openstack%2Fmistral~976387","triplet_id":"openstack%2Fmistral~master~I6ac391f65e9b951a02ebd50787a92ab0437f0fe2","project":"openstack/mistral","branch":"master","topic":"bp/support-more-ssh-key-types","attention_set":{},"removed_from_attention_set":{"38807":{"account":{"_account_id":38807,"name":"Mathieu Blot","display_name":"Mathieu Blot","email":"mathieu.blot@ovhcloud.com","username":"mathieublot"},"last_update":"2026-03-28 20:12:36.000000000","reason":"Change was submitted"}},"hashtags":[],"change_id":"I6ac391f65e9b951a02ebd50787a92ab0437f0fe2","subject":"Support ECDSA and Ed25519 SSH key types","status":"MERGED","created":"2026-02-11 13:23:53.000000000","updated":"2026-03-28 20:13:26.000000000","submitted":"2026-03-28 20:12:36.000000000","submitter":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"total_comment_count":2,"unresolved_comment_count":1,"has_review_started":true,"submission_id":"976387-bp/support-more-ssh-key-types","meta_rev_id":"98c81868759bca79a3f4bf3c2d8bcec494ca4e62","_number":976387,"virtual_id_number":976387,"owner":{"_account_id":38807,"name":"Mathieu Blot","display_name":"Mathieu Blot","email":"mathieu.blot@ovhcloud.com","username":"mathieublot"},"actions":{},"labels":{"Verified":{"approved":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"all":[{"tag":"autogenerated:zuul:gate","value":2,"date":"2026-03-28 20:12:36.000000000","permitted_voting_range":{"min":2,"max":2},"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},{"value":0,"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"}],"values":{"-2":"Fails","-1":"Doesn\u0027t seem to work"," 0":"No score","+1":"Works for me","+2":"Verified"},"description":"","default_value":0,"optional":true},"Code-Review":{"approved":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"all":[{"value":0,"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},{"value":2,"date":"2026-03-28 19:26:25.000000000","permitted_voting_range":{"min":2,"max":2},"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"}],"values":{"-2":"Do not merge","-1":"This patch needs further work before it can be merged"," 0":"No score","+1":"Looks good to me, but someone else must approve","+2":"Looks good to me (core reviewer)"},"description":"","default_value":0,"optional":true},"Workflow":{"approved":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"all":[{"value":0,"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},{"value":1,"date":"2026-03-28 19:26:25.000000000","permitted_voting_range":{"min":1,"max":1},"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"}],"values":{"-1":"Work in progress"," 0":"Ready for reviews","+1":"Approved"},"description":"","default_value":0,"optional":true}},"removable_reviewers":[],"reviewers":{"REVIEWER":[{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]}]},"pending_reviewers":{},"reviewer_updates":[{"updated":"2026-02-11 14:09:33.000000000","updated_by":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"reviewer":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"state":"REVIEWER"},{"updated":"2026-02-13 17:29:07.000000000","updated_by":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"reviewer":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"state":"CC"},{"updated":"2026-03-28 19:26:25.000000000","updated_by":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"reviewer":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"state":"REVIEWER"}],"messages":[{"id":"15f87937bc18d0449efa5d4e2715e17d2b3942ea","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":38807,"name":"Mathieu Blot","display_name":"Mathieu Blot","email":"mathieu.blot@ovhcloud.com","username":"mathieublot"},"date":"2026-02-11 13:23:53.000000000","message":"Uploaded patch set 1.","accounts_in_message":[],"_revision_number":1},{"id":"e4bc968cc94bc61a41ed8cc05ddb45bdf7598d88","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-02-11 14:09:33.000000000","message":"Patch Set 1: Verified-1\n\n(6 comments)\n\nBuild failed (check pipeline).  For information on how to proceed, see\nhttps://docs.opendev.org/opendev/infra-manual/latest/developers.html#automated-testing\nand https://docs.openstack.org/project-team-guide/testing.html#how-to-handle-test-failures\n\nhttps://zuul.opendev.org/t/openstack/buildset/8150da3b316e45e3836600675ff69fe3\n\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/d1701a28b6b04ffa9438521e24e63beb : FAILURE in 2m 56s\n- openstack-tox-py310 https://zuul.opendev.org/t/openstack/build/a56dd00867ee4d26a799701bd2a9a0db : SUCCESS in 10m 57s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/e2e67134701743cebdf2985e247187cc : SUCCESS in 9m 50s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/72c679963fb444e7977095aabcd01b2e : SUCCESS in 8m 22s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/646869927d4341fdbcbafbb48761d75d : SUCCESS in 17m 00s (non-voting)\n- mistral-devstack https://zuul.opendev.org/t/openstack/build/39f0b77062e9487a840f9afb8e8f081d : SUCCESS in 40m 52s\n- mistral-devstack-tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/34e48b3cba9f483bac58a253be370180 : SUCCESS in 38m 48s","accounts_in_message":[],"_revision_number":1},{"id":"255d17ecde873b4371d8bbe3500902de74acec34","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":38807,"name":"Mathieu Blot","display_name":"Mathieu Blot","email":"mathieu.blot@ovhcloud.com","username":"mathieublot"},"date":"2026-02-11 14:56:33.000000000","message":"Uploaded patch set 2.\n\nOutdated Votes:\n* Verified-1\n","accounts_in_message":[],"_revision_number":2},{"id":"d11e2d1cb687e51972a0f51f1cd71077f097cb05","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-02-11 15:48:07.000000000","message":"Patch Set 2: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/c1c7b21ccfbd4a66a0e0652f3e2f3a57\n\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/9142bee869ad4f2cba55520ea60b2bb9 : SUCCESS in 2m 23s\n- openstack-tox-py310 https://zuul.opendev.org/t/openstack/build/a19db04bce8646d5ac83412f6e487be1 : SUCCESS in 11m 01s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/204495e0f61844a1a03b8ea5db84eda7 : SUCCESS in 11m 26s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/0b6f1841e13c451db07b9cf301baa8dc : SUCCESS in 7m 49s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/cb20d2d767ce4e129e8b3066944115d7 : SUCCESS in 17m 03s (non-voting)\n- mistral-devstack https://zuul.opendev.org/t/openstack/build/5f7071de0548494fb0e50b9a611289ae : SUCCESS in 43m 48s\n- mistral-devstack-tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/cda207c6284640cb90859cfa6428d48d : SUCCESS in 45m 15s","accounts_in_message":[],"_revision_number":2},{"id":"76602579dbf14d381c5ca1797578c6db3f5da20d","author":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"date":"2026-02-13 17:29:07.000000000","message":"Patch Set 2:\n\n(1 comment)","accounts_in_message":[],"_revision_number":2},{"id":"c6f464c659c8ea14b9b424ebf6d048695fa93fb9","tag":"autogenerated:gerrit:newPatchSet","author":{"_account_id":38807,"name":"Mathieu Blot","display_name":"Mathieu Blot","email":"mathieu.blot@ovhcloud.com","username":"mathieublot"},"date":"2026-02-17 14:04:39.000000000","message":"Uploaded patch set 3.\n\nOutdated Votes:\n* Verified+1\n","accounts_in_message":[],"_revision_number":3},{"id":"829122f0240c54254e2ef9e49e173368b1052663","tag":"autogenerated:zuul:check","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-02-17 14:45:19.000000000","message":"Patch Set 3: Verified+1\n\nBuild succeeded (check pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/eb2ba15b6ad441728d2917e7574f140e\n\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/3a27184f76144967ab65780835ebe4c3 : SUCCESS in 2m 46s\n- openstack-tox-py310 https://zuul.opendev.org/t/openstack/build/58739de1214d46d2bba8796edc88aecd : SUCCESS in 9m 38s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/4962dedd924a4e54875cea29079b5946 : SUCCESS in 11m 22s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/3092df2669694dd6b66621595477cd66 : SUCCESS in 8m 52s\n- openstack-tox-cover https://zuul.opendev.org/t/openstack/build/d37f7fa0f2824e6ab6de3eacd99dab4f : SUCCESS in 16m 42s (non-voting)\n- mistral-devstack https://zuul.opendev.org/t/openstack/build/cfb126036cc2459a87ca1a96881938a3 : SUCCESS in 27m 52s\n- mistral-devstack-tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/9fc47c70db5f4e4c947a7fae5dc90af6 : SUCCESS in 33m 48s","accounts_in_message":[],"_revision_number":3},{"id":"8a3e003a9c1530323869e1433544bc2227fa6992","author":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"},"date":"2026-03-28 19:26:25.000000000","message":"Patch Set 3: Code-Review+2 Workflow+1\n\n(1 comment)","accounts_in_message":[],"_revision_number":3},{"id":"f8eb281081a2547ed39be83d4c2bca0bd1f56269","tag":"autogenerated:zuul:gate","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-03-28 19:26:50.000000000","message":"Patch Set 3: -Verified\n\nStarting gate jobs.","accounts_in_message":[],"_revision_number":3},{"id":"fbf5333d8c6b94572f1a3abe48a8d0a376b32a84","tag":"autogenerated:zuul:gate","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-03-28 20:12:36.000000000","message":"Patch Set 3: Verified+2\n\nBuild succeeded (gate pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/30ec69e042ba40bcbf57738230602c55\n\n- openstack-tox-pep8 https://zuul.opendev.org/t/openstack/build/a27db33876ff4284b69383feedaf5d51 : SUCCESS in 3m 19s\n- openstack-tox-py310 https://zuul.opendev.org/t/openstack/build/85720c92fc884e42bbf289407528c5c0 : SUCCESS in 9m 56s\n- openstack-tox-py313 https://zuul.opendev.org/t/openstack/build/01716fa9f544405292fc4b2c54c1d075 : SUCCESS in 10m 57s\n- openstack-tox-docs https://zuul.opendev.org/t/openstack/build/12ad27e2bc1d46bdbb96c66fd37e1ecf : SUCCESS in 4m 14s\n- mistral-devstack https://zuul.opendev.org/t/openstack/build/dfa8ba8abdb14eb7b250df41006e4af9 : SUCCESS in 38m 58s\n- mistral-devstack-tempest-ipv6-only https://zuul.opendev.org/t/openstack/build/2168b8225b14479f9dbabc21373f62d2 : SUCCESS in 40m 50s","accounts_in_message":[],"_revision_number":3},{"id":"50e18255add8f865b48f879f889a4ba00b1bbdb2","tag":"autogenerated:gerrit:merged","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-03-28 20:12:36.000000000","message":"Change has been successfully merged","accounts_in_message":[],"_revision_number":3},{"id":"98c81868759bca79a3f4bf3c2d8bcec494ca4e62","tag":"autogenerated:zuul:promote","author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"date":"2026-03-28 20:13:26.000000000","message":"Patch Set 3:\n\nBuild succeeded (promote pipeline).\nhttps://zuul.opendev.org/t/openstack/buildset/73ab804b0c514b1cb47506a6d7097505\n\n- promote-openstack-tox-docs https://zuul.opendev.org/t/openstack/build/9766cd8a637542c9b59ef97f79e0f9c1 : SUCCESS in 40s","accounts_in_message":[],"_revision_number":3}],"current_revision_number":3,"current_revision":"6b85b8165132267536e9f5848994b9dc3747d8c1","revisions":{"35b3973dbf8a5ef1efc866db0bff5146993a1117":{"kind":"REWORK","_number":1,"created":"2026-02-11 13:23:53.000000000","uploader":{"_account_id":38807,"name":"Mathieu Blot","display_name":"Mathieu Blot","email":"mathieu.blot@ovhcloud.com","username":"mathieublot"},"ref":"refs/changes/87/976387/1","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/mistral","ref":"refs/changes/87/976387/1","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/1 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/1 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/1 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/mistral refs/changes/87/976387/1"}}},"commit":{"parents":[{"commit":"a2259575a69a7dc3700a6b3d74b98deea41f2859","subject":"Add oslo.concurrency to mistral.conf namespace list","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/a2259575a69a7dc3700a6b3d74b98deea41f2859"}]}],"author":{"name":"mathieublot","email":"mathieu.blot@ovhcloud.com","date":"2026-02-10 20:57:02.000000000","tz":-300},"committer":{"name":"mathieublot","email":"mathieu.blot@ovhcloud.com","date":"2026-02-11 13:23:46.000000000","tz":-300},"subject":"Support ECDSA and Ed25519 SSH key types","message":"Support ECDSA and Ed25519 SSH key types\n\nThe _to_paramiko_private_key helper in ssh_utils was hardcoded to\nonly load RSA keys (paramiko.RSAKey). Users relying on ECDSA or\nEd25519 keys could not use SSH actions at all, resulting in\nan SSHException at connection time.\n\nRefactor _to_paramiko_private_key to iterate over the supported\nparamiko key classes (RSAKey, ECDSAKey, Ed25519Key) in order,\nreturning the first one that successfully parses the provided\nkey material. If none of the classes can load the key, the last\nexception encountered is re-raised so the caller still gets a\nmeaningful error.\n\nThis applies to both code paths: key provided as a string\n(private_key) and key loaded from a file (private_key_filename).\n\nAdd unit tests covering:\n- RSA, ECDSA, and Ed25519 keys from string and from file\n- Fallback order (RSA → ECDSA → Ed25519) via mocks\n- Invalid key material raises the last exception\n- Path traversal rejection (../ and ..\\)\n- Absolute vs. relative filename resolution\n- None returned when no key material is provided\n\nThe unit test was done with AI assistance.\n\nChange-Id: I6ac391f65e9b951a02ebd50787a92ab0437f0fe2\nSigned-off-by: mathieublot \u003cmathieu.blot@ovhcloud.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/35b3973dbf8a5ef1efc866db0bff5146993a1117"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/35b3973dbf8a5ef1efc866db0bff5146993a1117"}]},"branch":"refs/heads/master"},"b54f2754c909cc6536c6fcffa9fa560e67242fce":{"kind":"REWORK","_number":2,"created":"2026-02-11 14:56:33.000000000","uploader":{"_account_id":38807,"name":"Mathieu Blot","display_name":"Mathieu Blot","email":"mathieu.blot@ovhcloud.com","username":"mathieublot"},"ref":"refs/changes/87/976387/2","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/mistral","ref":"refs/changes/87/976387/2","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/2 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/2 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/2 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/mistral refs/changes/87/976387/2"}}},"commit":{"parents":[{"commit":"a2259575a69a7dc3700a6b3d74b98deea41f2859","subject":"Add oslo.concurrency to mistral.conf namespace list","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/a2259575a69a7dc3700a6b3d74b98deea41f2859"}]}],"author":{"name":"mathieublot","email":"mathieu.blot@ovhcloud.com","date":"2026-02-10 20:57:02.000000000","tz":-300},"committer":{"name":"mathieublot","email":"mathieu.blot@ovhcloud.com","date":"2026-02-11 14:55:48.000000000","tz":-300},"subject":"Support ECDSA and Ed25519 SSH key types","message":"Support ECDSA and Ed25519 SSH key types\n\nThe _to_paramiko_private_key helper in ssh_utils was hardcoded to\nonly load RSA keys (paramiko.RSAKey). Users relying on ECDSA or\nEd25519 keys could not use SSH actions at all, resulting in\nan SSHException at connection time.\n\nRefactor _to_paramiko_private_key to iterate over the supported\nparamiko key classes (RSAKey, ECDSAKey, Ed25519Key) in order,\nreturning the first one that successfully parses the provided\nkey material. If none of the classes can load the key, the last\nexception encountered is re-raised so the caller still gets a\nmeaningful error.\n\nThis applies to both code paths: key provided as a string\n(private_key) and key loaded from a file (private_key_filename).\n\nAdd unit tests covering:\n- RSA, ECDSA, and Ed25519 keys from string and from file\n- Fallback order (RSA → ECDSA → Ed25519) via mocks\n- Invalid key material raises the last exception\n- Path traversal rejection (../ and ..\\)\n- Absolute vs. relative filename resolution\n- None returned when no key material is provided\n\nThe unit test was done with AI assistance.\n\nChange-Id: I6ac391f65e9b951a02ebd50787a92ab0437f0fe2\nSigned-off-by: mathieublot \u003cmathieu.blot@ovhcloud.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/b54f2754c909cc6536c6fcffa9fa560e67242fce"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/b54f2754c909cc6536c6fcffa9fa560e67242fce"}]},"branch":"refs/heads/master"},"6b85b8165132267536e9f5848994b9dc3747d8c1":{"kind":"REWORK","_number":3,"created":"2026-02-17 14:04:39.000000000","uploader":{"_account_id":38807,"name":"Mathieu Blot","display_name":"Mathieu Blot","email":"mathieu.blot@ovhcloud.com","username":"mathieublot"},"ref":"refs/changes/87/976387/3","fetch":{"anonymous http":{"url":"https://review.opendev.org/openstack/mistral","ref":"refs/changes/87/976387/3","commands":{"Checkout":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/3 \u0026\u0026 git checkout FETCH_HEAD","Cherry Pick":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/3 \u0026\u0026 git cherry-pick FETCH_HEAD","Format Patch":"git fetch https://review.opendev.org/openstack/mistral refs/changes/87/976387/3 \u0026\u0026 git format-patch -1 --stdout FETCH_HEAD","Pull":"git pull https://review.opendev.org/openstack/mistral refs/changes/87/976387/3"}}},"commit":{"parents":[{"commit":"a2259575a69a7dc3700a6b3d74b98deea41f2859","subject":"Add oslo.concurrency to mistral.conf namespace list","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/a2259575a69a7dc3700a6b3d74b98deea41f2859"}]}],"author":{"name":"mathieublot","email":"mathieu.blot@ovhcloud.com","date":"2026-02-10 20:57:02.000000000","tz":-300},"committer":{"name":"mathieublot","email":"mathieu.blot@ovhcloud.com","date":"2026-02-17 14:04:16.000000000","tz":-300},"subject":"Support ECDSA and Ed25519 SSH key types","message":"Support ECDSA and Ed25519 SSH key types\n\nThe _to_paramiko_private_key helper in ssh_utils was hardcoded to\nonly load RSA keys (paramiko.RSAKey). Users relying on ECDSA or\nEd25519 keys could not use SSH actions at all, resulting in\nan SSHException at connection time.\n\nRefactor _to_paramiko_private_key to iterate over the supported\nparamiko key classes (RSAKey, ECDSAKey, Ed25519Key) in order,\nreturning the first one that successfully parses the provided\nkey material. If none of the classes can load the key, the last\nexception encountered is re-raised so the caller still gets a\nmeaningful error.\n\nThis applies to both code paths: key provided as a string\n(private_key) and key loaded from a file (private_key_filename).\n\nAdd unit tests covering:\n- RSA, ECDSA, and Ed25519 keys from string and from file\n- Fallback order (RSA → ECDSA → Ed25519) via mocks\n- Invalid key material raises the last exception\n- Path traversal rejection (../ and ..\\)\n- Absolute vs. relative filename resolution\n- None returned when no key material is provided\n\nThe unit test was done with AI assistance.\n\nChange-Id: I6ac391f65e9b951a02ebd50787a92ab0437f0fe2\nSigned-off-by: mathieublot \u003cmathieu.blot@ovhcloud.com\u003e\n","web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/6b85b8165132267536e9f5848994b9dc3747d8c1"}],"resolve_conflicts_web_links":[{"name":"gitea","tooltip":"Open in GitWeb","url":"https://opendev.org/openstack/mistral/commit/6b85b8165132267536e9f5848994b9dc3747d8c1"}]},"branch":"refs/heads/master"}},"requirements":[],"submit_records":[{"rule_name":"gerrit~DefaultSubmitRule","status":"CLOSED","labels":[{"label":"Verified","status":"MAY","applied_by":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]}},{"label":"Code-Review","status":"MAY","applied_by":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"}},{"label":"Workflow","status":"MAY","applied_by":{"_account_id":11583,"name":"Arnaud Morin","email":"arnaud.morin@gmail.com","username":"arnaudmorin"}}]}],"submit_requirements":[{"name":"Verified","description":"Verified in gate by CI","status":"SATISFIED","is_legacy":false,"submittability_expression_result":{"expression":"label:Verified\u003dMAX AND -label:Verified\u003dMIN","fulfilled":true,"status":"PASS","passing_atoms":["label:Verified\u003dMAX"],"failing_atoms":["label:Verified\u003dMIN"],"atom_explanations":{}}},{"name":"Code-Review","description":"Code reviewed by core reviewer","status":"SATISFIED","is_legacy":false,"submittability_expression_result":{"expression":"label:Code-Review\u003dMAX AND -label:Code-Review\u003dMIN","fulfilled":true,"status":"PASS","passing_atoms":["label:Code-Review\u003dMAX"],"failing_atoms":["label:Code-Review\u003dMIN"],"atom_explanations":{}}},{"name":"Workflow","description":"Approved for gate by core reviewer","status":"SATISFIED","is_legacy":false,"submittability_expression_result":{"expression":"label:Workflow\u003dMAX AND -label:Workflow\u003dMIN","fulfilled":true,"status":"PASS","passing_atoms":["label:Workflow\u003dMAX"],"failing_atoms":["label:Workflow\u003dMIN"],"atom_explanations":{}}}]}
