-
Notifications
You must be signed in to change notification settings - Fork 356
Disable external process commands in HTTP + On-Behalf-Of mode #1522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -81,4 +81,14 @@ public class ServiceStartOptions | |
| /// </summary> | ||
| [JsonPropertyName("supportLoggingFolder")] | ||
| public string? SupportLoggingFolder { get; set; } = null; | ||
|
|
||
| /// <summary> | ||
| /// Determines whether the server is running in HTTP mode with On-Behalf-Of authentication. | ||
| /// </summary> | ||
| /// <returns>True if running in HTTP transport with On-Behalf-Of authentication; false otherwise.</returns> | ||
| public bool IsHttpOnBehalfOfMode() | ||
| { | ||
| return Transport == TransportTypes.Http | ||
| && OutgoingAuthStrategy == OutgoingAuthStrategy.UseOnBehalfOf; | ||
| } | ||
|
Comment on lines
+89
to
+93
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| changes: | ||
| - section: "Features Added" | ||
| description: "Disable external process commands (azqr) in HTTP + On-Behalf-Of mode for security" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| using Azure.Mcp.Core.Areas.Server.Options; | ||
| using Azure.Mcp.Core.Extensions; | ||
| using Azure.Mcp.Tools.Extension.Commands; | ||
| using Azure.Mcp.Tools.Extension.Services; | ||
|
|
@@ -32,8 +33,12 @@ public CommandGroup RegisterCommands(IServiceProvider serviceProvider) | |
|
|
||
| // Azure CLI and Azure Developer CLI tools are hidden | ||
| // extension.AddCommand("az", new AzCommand(loggerFactory.CreateLogger<AzCommand>())); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd recommend removing this comment OR putting it into the new |
||
| var azqr = serviceProvider.GetRequiredService<AzqrCommand>(); | ||
| extension.AddCommand(azqr.Name, azqr); | ||
|
|
||
| if (ShouldExposeExternalProcessCommands(serviceProvider)) | ||
| { | ||
| var azqr = serviceProvider.GetRequiredService<AzqrCommand>(); | ||
| extension.AddCommand(azqr.Name, azqr); | ||
| } | ||
|
|
||
| var cli = new CommandGroup("cli", "Commands for helping users to use CLI tools for Azure services operations. Includes operations for generating Azure CLI commands and getting installation instructions for Azure CLI, Azure Developer CLI and Azure Core Function Tools CLI."); | ||
| extension.AddSubGroup(cli); | ||
|
|
@@ -44,4 +49,26 @@ public CommandGroup RegisterCommands(IServiceProvider serviceProvider) | |
| cli.AddCommand(cliInstallCommand.Name, cliInstallCommand); | ||
| return extension; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Determines whether extension commands that use external process execution should be exposed. | ||
| /// External process commands (like azqr, azcli, azd) use <see cref="IExternalProcessService"/> to spawn | ||
| /// local processes. In HTTP + On-Behalf-Of mode, spawning child processes on a remote server is a security | ||
| /// risk: processes run under the server's host identity (not the OBO user's context), and malicious or | ||
| /// excessive requests could exhaust resources. | ||
| /// </summary> | ||
| /// <param name="serviceProvider">The service provider to resolve ServiceStartOptions from.</param> | ||
| /// <returns>True if external process commands should be exposed; false otherwise.</returns> | ||
| private static bool ShouldExposeExternalProcessCommands(IServiceProvider serviceProvider) | ||
| { | ||
| ServiceStartOptions? startOptions = serviceProvider.GetService<ServiceStartOptions>(); | ||
|
|
||
| if (startOptions is null) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want some modern C# Totally optional. Current code is fine. Just teaching.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks, will use type pattern matching here |
||
| { | ||
| // First container (CLI routing) - startOptions not available, allow all commands | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Now, I know what this means, but I doubt anyone else would. Please reference the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point - yes, the multi-container setup is pretty confusing :). Let me link to the entry point / program.cs where that is happening. |
||
| return true; | ||
| } | ||
|
|
||
| return !startOptions.IsHttpOnBehalfOfMode(); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Subjective style: this can be a property which looks a subjectively cleaner with c# syntax.
At the end of the day, both are creating parameterless methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks - yes, that’s actually what Copilot suggested. I was thinking it could be a method since we’re "computing" a boolean (coming from a Java mindset), but let’s go with a property given that’s more idiomatic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C# properties are a hybrid between fields and methods. While writing code, they can be referenced using field-like syntax (i.e., usage infers reading vs writing), but during compilation, they are translated into methods.