You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Apply command-boundary workload/datasource validation to DPP protect and policy create surfaces
Context
PR #2726 (NEW-4) added a command-boundary validator on azmcp_azurebackup_protectableitem_list --workload-type so that unknown values are rejected as a 400 ValidationError instead of leaking the service-layer ArgumentException as a 500. That fix only covers the RSV-only protectableitem_list command, which was the surface called out in the telemetry-triaged report.
A code audit during PR #2726 review found the same anti-pattern on two additional surfaces — both DPP-backed — that were not in the original telemetry report. This issue tracks fixing them in a separate, scoped PR.
All three currently surface as HTTP 500 / InternalServerError to MCP clients, hiding what is really a user-input mistake.
PolicyCreateValidator already does business-rule validation for the policy create command but does not validate that WorkloadType is in any known set.
Proposed fix
Mirror the NEW-4 pattern, but with DPP-aware allowlists:
ProtectedItemProtectCommand --datasource-type
Add a command.Validators.Add(...) that reads the value via commandResult.GetValueOrDefault<string>(AzureBackupOptionDefinitions.DatasourceType.Name) and rejects when the value is non-null and not in DppDatasourceRegistry.KnownTypeNamesand not a recognized ARM resource type (via DppDatasourceRegistry.TryAutoDetect).
Use the same "Unknown DPP workload type '...'. Supported tokens: …" message format as the service-layer throw so the error is consistent across layers.
PolicyCreateCommand --workload-type
Add a validator that accepts any token in the union of RsvDatasourceRegistry.KnownTypeNames and DppDatasourceRegistry.KnownTypeNames. If --vault-type is also supplied on the command line, narrow the allowed set to just that backend's tokens.
Keep the service-layer throws in place as defense-in-depth (same approach as NEW-4 on RsvBackupOperations.NormalizeWorkloadTypeForFilter).
ExecuteAsync_RejectsUnknownDatasourceType_AsValidationError on ProtectedItemProtectCommandTests (including whitespace cases: " ", "\t ").
ExecuteAsync_RejectsUnknownWorkloadType_AsValidationError on PolicyCreateCommandTests (including the vault-type narrowing case where an RSV-only token is rejected when --vault-type DPP is specified, and vice versa).
Assert BadRequest status, "Unknown" substring in the message, and Service.DidNotReceive().
Out of scope
Anything not on the --datasource-type / --workload-type parameter surfaces.
Behavior change of RsvDatasourceRegistry.ResolveOrDefault (which still needs to throw as defense-in-depth).
Telemetry tag changes.
Acceptance criteria
Unknown values passed to --datasource-type on protecteditem protect (DPP path) return BadRequest (HTTP 400) with an actionable error message and never reach DppBackupOperations.ProtectItemAsync.
Unknown values passed to --workload-type on policy create return BadRequest (HTTP 400) and never reach the registry Resolve call.
All existing AzureBackup unit tests continue to pass.
New unit tests cover the rejection paths including whitespace inputs.
No live test re-recording required (the changes are command-boundary only, no Azure traffic).
Apply command-boundary workload/datasource validation to DPP
protectandpolicy createsurfacesContext
PR #2726 (NEW-4) added a command-boundary validator on
azmcp_azurebackup_protectableitem_list --workload-typeso that unknown values are rejected as a 400ValidationErrorinstead of leaking the service-layerArgumentExceptionas a 500. That fix only covers the RSV-onlyprotectableitem_listcommand, which was the surface called out in the telemetry-triaged report.A code audit during PR #2726 review found the same anti-pattern on two additional surfaces — both DPP-backed — that were not in the original telemetry report. This issue tracks fixing them in a separate, scoped PR.
Affected surfaces
azmcp_azurebackup_protecteditem_protect(DPP path)--datasource-typeDppBackupOperations.ProtectItemAsync→ResolveProfile→DppDatasourceRegistry.ResolvethrowsArgumentException("Unknown DPP workload type '...'")azmcp_azurebackup_policy_create(DPP path)--workload-typeDppBackupOperations.CreatePolicyAsync→DppDatasourceRegistry.Resolve(workloadType)throwsArgumentExceptionazmcp_azurebackup_policy_create(RSV path)--workload-typeRsvBackupOperations.CreatePolicy→RsvDatasourceRegistry.ResolveOrDefaultthrowsArgumentExceptionAll three currently surface as HTTP 500 /
InternalServerErrorto MCP clients, hiding what is really a user-input mistake.PolicyCreateValidatoralready does business-rule validation for thepolicy createcommand but does not validate thatWorkloadTypeis in any known set.Proposed fix
Mirror the NEW-4 pattern, but with DPP-aware allowlists:
ProtectedItemProtectCommand --datasource-typecommand.Validators.Add(...)that reads the value viacommandResult.GetValueOrDefault<string>(AzureBackupOptionDefinitions.DatasourceType.Name)and rejects when the value is non-null and not inDppDatasourceRegistry.KnownTypeNamesand not a recognized ARM resource type (viaDppDatasourceRegistry.TryAutoDetect).PolicyCreateCommand --workload-typeRsvDatasourceRegistry.KnownTypeNamesandDppDatasourceRegistry.KnownTypeNames. If--vault-typeis also supplied on the command line, narrow the allowed set to just that backend's tokens.Keep the service-layer throws in place as defense-in-depth (same approach as NEW-4 on
RsvBackupOperations.NormalizeWorkloadTypeForFilter).Tests — extend the unit-test patterns introduced in PR azurebackup: fix telemetry-triaged bugs NEW-1, NEW-3, NEW-4 #2726:
ExecuteAsync_RejectsUnknownDatasourceType_AsValidationErroronProtectedItemProtectCommandTests(including whitespace cases:" ","\t ").ExecuteAsync_RejectsUnknownWorkloadType_AsValidationErroronPolicyCreateCommandTests(including the vault-type narrowing case where an RSV-only token is rejected when--vault-type DPPis specified, and vice versa).BadRequeststatus,"Unknown"substring in the message, andService.DidNotReceive().Out of scope
--datasource-type/--workload-typeparameter surfaces.RsvDatasourceRegistry.ResolveOrDefault(which still needs to throw as defense-in-depth).Acceptance criteria
--datasource-typeonprotecteditem protect(DPP path) returnBadRequest(HTTP 400) with an actionable error message and never reachDppBackupOperations.ProtectItemAsync.--workload-typeonpolicy createreturnBadRequest(HTTP 400) and never reach the registryResolvecall.Related
protectableitem_listvalidator)