Skip to content

Validate ServerId against local machine in Set-AzStorageSyncServer#29448

Draft
stefong99 wants to merge 4 commits intoAzure:mainfrom
stefong99:stefong/fix-patch-applicationid
Draft

Validate ServerId against local machine in Set-AzStorageSyncServer#29448
stefong99 wants to merge 4 commits intoAzure:mainfrom
stefong99:stefong/fix-patch-applicationid

Conversation

@stefong99
Copy link
Copy Markdown
Contributor

When ServerId is explicitly provided, call GetSyncServerId() via IEcsManagement to retrieve the local machine's server ID and verify it matches. This prevents accidental cross-machine misuse with a clear error message.

Also fix MockEcsManagementInteropClient.GetSyncServerId to use HttpMockServer.GetVariable for deterministic behavior in test playback mode.

Description

Mandatory Checklist

  • SHOULD update ChangeLog.md file(s) appropriately
    • Update src/{{SERVICE}}/{{SERVICE}}/ChangeLog.md.
      • A snippet outlining the change(s) made in the PR should be written under the ## Upcoming Release header in the past tense.
    • Should not change ChangeLog.md if no new release is required, such as fixing test case only.
  • SHOULD regenerate markdown help files if there is cmdlet API change. Instruction
  • SHOULD have proper test coverage for changes in pull request.
  • SHOULD NOT adjust version of module manually in pull request

stefong99 and others added 4 commits April 24, 2026 15:18
When ServerId is explicitly provided, call GetSyncServerId() via IEcsManagement
to retrieve the local machine's server ID and verify it matches. This prevents
accidental cross-machine misuse with a clear error message.

Also fix MockEcsManagementInteropClient.GetSyncServerId to use
HttpMockServer.GetVariable for deterministic behavior in test playback mode.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When ServerId is not explicitly passed to Set-AzStorageSyncServer,
call GetSyncServerId() to resolve it from the local machine automatically.
Remove the explicit validation block since the value is always sourced
from the local machine in that path.

Also fix RegisteredServers.Get and error messages to use the resolved
resourceName instead of the raw ServerId parameter.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When ServerId is explicitly passed, still validate it against the local
machine's server ID via GetSyncServerId(). When it is not passed, auto-
populate from the local machine (no validation needed).

Refactored to call GetSyncServerId() once and share the result across
both branches.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Refactor: call GetSyncServerId() once upfront before resolving either
parameter set, then validate the resolved resourceName against the local
machine's server ID in all cases (InputObject, explicit ServerId, and
auto-populated ServerId).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 24, 2026 22:41
@azure-client-tools-bot-prd
Copy link
Copy Markdown

Thanks for your contribution! The pull request validation has started. Please revisit this comment for updated status.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens Set-AzStorageSyncServer by validating that an explicitly targeted ServerId matches the local machine’s Azure File Sync agent server ID, preventing accidental cross-machine operations. It also updates the test mock for GetSyncServerId() to be deterministic in playback mode.

Changes:

  • Added local-machine ServerId retrieval via IEcsManagement.GetSyncServerId() and enforced match with the cmdlet target server ID.
  • Updated RegisteredServers.Get(...) and “not found” messaging to use the resolved/validated server ID.
  • Made MockEcsManagementInteropClient.GetSyncServerId() deterministic by using HttpMockServer.GetVariable(...) during playback/record.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/StorageSync/StorageSync/RegisteredServer/SetRegisteredServerCommand.cs Retrieves local server ID via ECS interop and validates it matches the cmdlet’s target ServerId before proceeding.
src/StorageSync/StorageSync.Test/Common/MockEcsManagementInteropClient.cs Ensures repeatable GetSyncServerId() values across test recording/playback.

Comment on lines +145 to +149
IEcsManagement ecsManagement = StorageSyncClientWrapper.StorageSyncResourceManager.CreateEcsManagement();
int hr = ecsManagement.GetSyncServerId(out string localServerId);
if (hr != 0 || !Guid.TryParse(localServerId, out Guid localServerGuid))
{
throw new PSArgumentException("Unable to retrieve the local server ID. Ensure the Azure File Sync agent is installed and running.");
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

IEcsManagement implements IDisposable (and the real implementation wraps a COM object). Wrap the instance returned from CreateEcsManagement() in a using/try/finally to ensure COM handles are released promptly.

Suggested change
IEcsManagement ecsManagement = StorageSyncClientWrapper.StorageSyncResourceManager.CreateEcsManagement();
int hr = ecsManagement.GetSyncServerId(out string localServerId);
if (hr != 0 || !Guid.TryParse(localServerId, out Guid localServerGuid))
{
throw new PSArgumentException("Unable to retrieve the local server ID. Ensure the Azure File Sync agent is installed and running.");
string localServerId;
Guid localServerGuid;
using (IEcsManagement ecsManagement = StorageSyncClientWrapper.StorageSyncResourceManager.CreateEcsManagement())
{
int hr = ecsManagement.GetSyncServerId(out localServerId);
if (hr != 0 || !Guid.TryParse(localServerId, out localServerGuid))
{
throw new PSArgumentException("Unable to retrieve the local server ID. Ensure the Azure File Sync agent is installed and running.");
}

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +151
IEcsManagement ecsManagement = StorageSyncClientWrapper.StorageSyncResourceManager.CreateEcsManagement();
int hr = ecsManagement.GetSyncServerId(out string localServerId);
if (hr != 0 || !Guid.TryParse(localServerId, out Guid localServerGuid))
{
throw new PSArgumentException("Unable to retrieve the local server ID. Ensure the Azure File Sync agent is installed and running.");
}

Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The cmdlet calls into the local agent (GetSyncServerId) before verifying that -Identity was supplied. This can change the error users get when they omit -Identity (and can fail on machines without the agent even though the invocation is already invalid). Consider checking/enforcing -Identity first, then retrieving/validating the local server ID.

Copilot uses AI. Check for mistakes.
Comment on lines +165 to 169
if (!Guid.TryParse(resourceName, out Guid resourceServerGuid) || resourceServerGuid != localServerGuid)
{
throw new PSArgumentException($"The provided ServerId '{resourceName}' does not match the local machine's server ID '{localServerGuid}'. Run this command on the correct server.");
}

Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

The error message conflates two different cases: (1) ServerId is not a valid GUID and (2) it is a valid GUID but doesn’t match the local machine. Consider splitting these conditions so an invalid GUID gets a clear format/validation error, and consider wording that also makes sense when InputObject is used (not just when -ServerId is explicitly provided).

Suggested change
if (!Guid.TryParse(resourceName, out Guid resourceServerGuid) || resourceServerGuid != localServerGuid)
{
throw new PSArgumentException($"The provided ServerId '{resourceName}' does not match the local machine's server ID '{localServerGuid}'. Run this command on the correct server.");
}
if (!Guid.TryParse(resourceName, out Guid resourceServerGuid))
{
throw new PSArgumentException($"The server ID '{resourceName}' is not a valid GUID.");
}
if (resourceServerGuid != localServerGuid)
{
throw new PSArgumentException($"The server ID '{resourceName}' does not match the local machine's server ID '{localServerGuid}'. Run this command on the correct server.");
}

Copilot uses AI. Check for mistakes.
Comment on lines +165 to 168
if (!Guid.TryParse(resourceName, out Guid resourceServerGuid) || resourceServerGuid != localServerGuid)
{
throw new PSArgumentException($"The provided ServerId '{resourceName}' does not match the local machine's server ID '{localServerGuid}'. Run this command on the correct server.");
}
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

New behavior (rejecting a non-local ServerId) doesn’t appear to have a negative test. Since StorageSync.Test/ScenarioTests/RegisteredServerTests.ps1 already covers Set-AzStorageSyncServer success paths, add a scenario test that passes a different GUID and asserts the cmdlet throws the expected PSArgumentException so playback/recording covers this validation.

Copilot generated this review using guidance from repository custom instructions.
@VeryEarly
Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines
Copy link
Copy Markdown
Contributor

Azure Pipelines successfully started running 3 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants