Skip to content
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

Support for credential providers deployed via .NET tools #12567

Open
JohnSchmeichel opened this issue Apr 27, 2023 · 5 comments
Open

Support for credential providers deployed via .NET tools #12567

JohnSchmeichel opened this issue Apr 27, 2023 · 5 comments
Assignees
Labels
Area:Authentication Area:Plugin V2 plugin w/ cross platform support Priority:2 Issues for the current backlog. Product:dotnet.exe Type:Feature

Comments

@JohnSchmeichel
Copy link

JohnSchmeichel commented Apr 27, 2023

NuGet Product(s) Affected

NuGet.exe, MSBuild.exe, dotnet.exe, NuGet SDK

Current Behavior

Currently, credential providers support *.exe for .NET Framework or *.dll for .NET Core, and are usually split between two folders under the NuGet credential provider base path. For .NET Framework the providers are discovered by searching credentialprovider*.exe and executing that program, and for .NET Core they are discovered by searching credentialprovider*.dll and executing dotnet <credentialprovider>.dll. Prior to .NET Core 2.0 this split was required as .NET Core only supported platform agnostic dll's (with the side affect of excluding platform dependent credential providers not based on .NET). With the latest versions of .NET however, this split is no longer necessary and requires multiple versions to be supported and deployed. This is also reinforced by the two plugin path environment variables NUGET_NETFX_PLUGIN_PATHS and NUGET_NETCORE_PLUGIN_PATHS which need to be set per framework version.

A deployment solution for dotnet is .NET tools which provide a seamless .NET install and management experience for NuGet packages. Using .NET tools as a deployment mechanism has been a recurring feature ask for users of the .NET ecosystem which need to authenticate with private repositories. The ideal workflow would be (for private repositories like Azure DevOps):

  1. Customers have dotnet CLI tools installed
  2. Run dotnet tool install -g Microsoft.CredentialProviders
  3. Run dotnet restore with a private endpoint and it 'just works' (e.g. credential providers from step 2 are used during credential acquisition and used to authenticate against private endpoints)

This almost works today, but for Windows .NET Framework only. The goal is to support this cross-platform for all supported .NET runtimes.

Problems

This work for Windows and .NET Framework today with the following caveats:

  1. You must use the "tool path" option when installing to get the tool in a path known by NuGet. By default .NET tools are installed to %USERPROFILE%\.dotnet\tools which is a location not examined by NuGet today. This can be specified explicitly, but can be error prone and doesn't take into account any environment customization:
    dotnet tool install -g Microsoft.CredentialProviders --tool-path %USERPROFILE%\.nuget\plugins\netfx\CredentialProvider.Microsoft
    
  2. .NET tools will wrap up the .NET application and layout with a single *.exe and hide all the details of the NuGet package and associated files in a .store directory as an implementation detail. This works for .NET Framework which exclusively checks for *.exe, but not for .NET Core.

Deployment via a .NET tool doesn't work for .NET Core or cross platform for the following reasons:

  1. For Windows .NET tools will always use a *.exe extension. This doesn't work for .NET Core as that requires a *.dll to be invoked from dotnet, even if the .NET tool exe would otherwise work for both versions.
  2. For Linux/OSX the executable will not have any extension, but instead just have an executable with the execute bit (+x) set on it. E.g.:
    ~$ dotnet tool install -g my-dotnet-tool
    You can invoke the tool using the following command: my-dotnet-tool
    Tool 'my-dotnet-tool' (version '0.0.1') was successfully installed.
    
    ~$ ls -l -a ~/.dotnet/tools
    total 120
    drwxrwxrwx  3 user user   4096 Mar 25  2019 .
    drwxrwxrwx 13 user user   4096 Mar 30 17:34 ..
    drwxrwxrwx  4 user user   4096 Mar 25  2019 .store
    -rwxr-xr-x  1 user user 106744 Mar 25  2019 my-dotnet-tool
    

This doesn't work as NuGet is exclusively looking for *.exe or *.dll

Desired Behavior

The following changes in behavior would be required to make the proposal work:

1. Support platform appropriate executables

For Windows: support *.exe for both .NET Framework and .NET Core.
For Linux/OSX: support extensionless executables (+x bit set).

2. Support single plugin path environment variable

In order to ship a single credential provider that works for both .NET Framework and .NET Core that doesn't conflict with the existing semantics of the NUGET_NETFX_PLUGIN_PATHS and NUGET_NETCORE_PLUGIN_PATHS environment variables, a new environment variable should be introduced that supports the new semantics for # 1 above. It's possible that NUGET_PLUGIN_PATHS can be repurposed here, but that currently has lower precedence that the framework versions.

3. Support the .NET tool default installation location for credential providers

The default .NET tool installation directory should be included when discovering credential providers. This will simplify the installation and should reduce cases where tools are installed to a location that NuGet does not consider, reducing troubleshooting and support cases.

Additional Context

The overall context and vision for the credential providers that support Azure DevOps (nuget, npm, python, etc.) is that they should be supported and easily installable in the ecosystems they are used in. For .NET using the dotnet CLI that means installable using dotnet tool install, for npm that means npm install, etc. Currently, various installation scripts are required, per platform, which already assume a set of tools and configuration about the users environment (PowerShell/pwsh, bash/sh, etc.).

@JohnSchmeichel JohnSchmeichel added Triage:Untriaged Type:DCR Design Change Request labels Apr 27, 2023
@zivkan
Copy link
Member

zivkan commented Apr 28, 2023

FWIW, some intelligent person proposed the same thing a few years ago :)

@JohnSchmeichel
Copy link
Author

FWIW, some intelligent person proposed the same thing a few years ago :)

Love it! Definitely worth considering incorporating some of those ideas into this proposal as well, like the new package type and discovery.

@jeffkl jeffkl added the Priority:2 Issues for the current backlog. label May 4, 2023
@jeffkl
Copy link
Contributor

jeffkl commented May 4, 2023

Team Triage: @kartheekp-ms it would be good to have a design by 2023-09.

@mungojam
Copy link

What's the high level idea for detecting a nuget plugin Vs any other .net tool? You wouldn't want to run every installed tool with -Plugin

@zivkan
Copy link
Member

zivkan commented Sep 27, 2023

There's no design for this feature yet. That's something that whoever proposes a design needs to figure out.

Personally, I don't think that cred providers should be installed via dotnet tool install. Instead, I proposed something else. However, someone needs to create an actual spec with a design that goes through a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area:Authentication Area:Plugin V2 plugin w/ cross platform support Priority:2 Issues for the current backlog. Product:dotnet.exe Type:Feature
Projects
None yet
Development

No branches or pull requests

5 participants