Skip to content

[SSH] Fix #8994: Warn when certificate permissions cannot be set - #10374

Open
Aditya Pujara (a0x1ab) wants to merge 1 commit into
Azure:mainfrom
a0x1ab:agent-assist/azure-azure-cli-extensions-issue-8994-c665cf27e2a7
Open

Aditya Pujara (a0x1ab) wants to merge 1 commit into
Azure:mainfrom
a0x1ab:agent-assist/azure-azure-cli-extensions-issue-8994-c665cf27e2a7

Conversation

@a0x1ab

@a0x1ab Aditya Pujara (a0x1ab) commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

🤖 PR Validation — ️✔️ All clear

Breaking Changes
️✔️ None

Description

Fixes #8994.

Warn when certificate permissions cannot be set.


This checklist is used to make sure that common guidelines for a pull request are followed.

Related command

az ssh cert

General Guidelines

  • Have you run azdev style <YOUR_EXT> locally? (pip install azdev required)
  • Have you run python scripts/ci/test_index.py -q locally? (pip install azdev required)
  • My extension version conforms to the Extension version schema

For new extensions:

About Extension Publish

There is a pipeline to automatically build, upload and publish extension wheels.
Once your pull request is merged into main branch, a new pull request will be created to update src/index.json automatically.
You only need to update the version information in file setup.py and historical information in file HISTORY.rst in your PR but do not modify src/index.json.

AI-generated by X Engineering Agent via Azure AI Foundry.
Foundry-Job: c665cf27e2a7a9fad909c04e4a54bab62f364692a93fffc7457a9efdf862bafd
@a0x1ab Aditya Pujara (a0x1ab) added the Request X Engineering Agent Ask the agent to triage this issue or review this PR label Sep 21, 2026
@azure-client-tools-bot-prd

Copy link
Copy Markdown

Hi Aditya Pujara (@a0x1ab),
Please write the description of changes which can be perceived by customers into HISTORY.rst.
If you want to release a new extension version, please update the version in pyproject.toml (or setup.py, if the extension has not migrated yet) as well.

@x-engineering-agent
x-engineering-agent Bot marked this pull request as ready for review September 21, 2026 09:32
Copilot AI lite review requested due to automatic review settings September 21, 2026 09:32
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

No unresolved blocking issues were identified in the reviewed changes.

Review effort: Lite
Findings: None

What changed in this PR

Updates the SSH extension to warn when certificate permissions cannot be set while preserving fatal certificate-writing errors.

Changes:

  • Bumps version to 2.0.10 and documents the fix.
  • Handles permission-setting failures with warnings.
  • Adds coverage for warning and fatal error paths.
File Summary
src/​ssh/​setup.py Bumps the extension version.
src/​ssh/​HISTORY.rst Documents the bug fix.
src/​ssh/​azext_ssh/​tests/​latest/​test_custom.py Adds behavioral coverage.
src/​ssh/​azext_ssh/​custom.py Warns on permission-setting failures.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@a0x1ab

Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

@x-engineering-agent

Copy link
Copy Markdown

Live test results — azdev test --live --series (changed test files only)

✅ PASS

Selectors: azext_ssh.test_custom (extension)
PR head ref: agent-assist/azure-azure-cli-extensions-issue-8994-c665cf27e2a7
PR head sha: 4106d222f8134a65e29315e63d00a00a4110826f
PR base ref: main
New test files in PR: false

Changed test files run
src/ssh/azext_ssh/tests/latest/test_custom.py

Workflow run: https://github.com/Azure/issue-sentinel/actions/runs/35585270187

Last 80 lines of azdev output

=============
| Run Tests |
=============


test index found: /home/runner/.azdev/env_config/home/runner/work/issue-sentinel/issue-sentinel/.venv/test_index/latest.json

Test on modules: azext_ssh.test_custom

WARNING: RUNNING TESTS LIVE
The tests are set to run against current profile "latest"
============================= test session starts ==============================
platform linux -- Python 3.12.14, pytest-9.1.1, pluggy-1.6.0 -- /home/runner/work/issue-sentinel/issue-sentinel/.venv/bin/python
cachedir: .pytest_cache
rootdir: /home/runner/work/issue-sentinel/issue-sentinel/azure-cli-extensions
configfile: pytest.ini
plugins: forked-1.7.5, xdist-3.8.0
collecting ... collected 35 items

azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_assert_args_cert_with_no_user PASSED [  2%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_assert_args_invalid_cert_filepath PASSED [  5%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_assert_args_invalid_resource_type PASSED [  8%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_assert_args_ip_with_vm_or_rg PASSED [ 11%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_assert_args_no_ip_or_vm PASSED [ 14%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_assert_args_vm_rg_mismatch PASSED [ 17%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_check_or_create_public_private_files_defaults PASSED [ 20%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_check_or_create_public_private_files_defaults_with_cred_folder PASSED [ 22%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_check_or_create_public_private_files_no_private PASSED [ 25%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_check_or_create_public_private_files_no_public PASSED [ 28%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_delete_credentials_not_cloudshell PASSED [ 31%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_do_ssh_arc_op_aad_user PASSED [ 34%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_do_ssh_op_aad_user_compute PASSED [ 37%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_do_ssh_op_arc_local_user PASSED [ 40%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_do_ssh_op_local_user_compute PASSED [ 42%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_do_ssh_op_no_public_ip PASSED [ 45%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_get_and_write_certificate_generation_error PASSED [ 48%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_get_modulus_exponent_file_not_found PASSED [ 51%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_get_modulus_exponent_parse_error PASSED [ 54%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_get_modulus_exponent_success PASSED [ 57%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_arc PASSED [ 60%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_cert PASSED [ 62%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_cert_cert_file_missing PASSED [ 65%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_cert_no_args PASSED [ 68%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_config_cred_folder PASSED [ 71%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_config_credentials_folder_and_key PASSED [ 74%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_config_no_cred_folder PASSED [ 77%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_vm PASSED [ 80%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_vm_debug PASSED [ 82%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_vm_delete_credentials_cloudshell PASSED [ 85%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_ssh_vm_rdp PASSED [ 88%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_write_cert_file PASSED [ 91%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_write_cert_file_io_errors_are_fatal PASSED [ 94%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_write_cert_file_permission_errors PASSED [ 97%]
azure-cli-extensions/src/ssh/azext_ssh/tests/latest/test_custom.py::SshCustomCommandTest::test_write_cert_file_unexpected_permission_error_is_fatal PASSED [100%]

- generated xml file: /home/runner/work/issue-sentinel/issue-sentinel/test-output/results.xml -
============================== 35 passed in 0.68s ==============================

Posted by the X Engineering Agent live-test workflow.

@x-engineering-agent x-engineering-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aditya Pujara (@a0x1ab)

Review

No blocking findings identified in the changed lines at 4106d222f8.

The certificate writer limits warning-only handling to oschmod.set_mode: unsupported permissions and a missing Windows DACL no longer discard an otherwise written public certificate. File open/write/close errors, certificate-generation errors, and unexpected exception types still propagate. The regression tests check the returned path, exact on-disk certificate content, warning details, and those fatal-error boundaries. The 2.0.10 version and release-history entry agree, and no dependency pin changed.

Upstream CI

All 25 reported checks passed for this head; none are pending, failed, or awaiting replacement after cancellation.

Test validation

  • Live test: Passed. Workflow run
  • Regression coverage: Not applicable to the changed files.

The extension-specific tests in src/ssh/azext_ssh/tests/latest/test_custom.py cover the permission-error behavior. The CLI command-module coverage detector is not applicable to this extension; that does not mean regression coverage is absent. The missing-DACL case is simulated, so this evidence does not establish behavior on every Windows filesystem.

Risk assessment

34/100 · Medium · High confidence

The Medium rating is driven by public CLI behavior, dependency or supply chain.

  • Change scope: 4 changed files, 99 changed lines (+95 / -4), including 2 production files.
  • Affected components: ssh
  • Risk drivers: public CLI behavior (+18); dependency or supply chain (+18)
  • Regression evidence: Changed regression tests are included, reducing risk.
  • Confidence: High because changed-line patches were available for every production file.
  • Required review: Owning-squad review is required for ssh before merge.

@x-engineering-agent x-engineering-agent Bot added X Engineering Agent Reviewed Agent reviewed this PR and removed Request X Engineering Agent Ask the agent to triage this issue or review this PR labels Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

X Engineering Agent Reviewed Agent reviewed this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Writing a cert file to a directory without permission system may fail

2 participants