Quickly Map Your NuGet Packages to Sources

Erick Yondon

Package Source Mapper

When we introduced Package Source Mapping late last year, we noticed a certain challenge to make onboarding to using the feature easier. Could there be a way for us to automatically generate a NuGet.config for you based on your project’s known packages and sources?

We started to develop a tool that does just that for you. Learn more about how you can use it below.

Getting the Tool

You can download the tool directly from NuGet.org as a dotnet tool:

dotnet tool install --global NuGet.PackageSourceMapper --version 0.1.3-preview.22218.1

Alternatively, you can download and compile the code locally if you prefer to.

Using Package Source Mapper

The package source mapper tool requires you to have completed a successful package restore in which it will read each respective .nupkg.metadata file generated as part of your build to best understand how you map your respective packages and sources.

Here’s what one of those files looks like. Take a package like NuGet.Protocol that was restored successfully:

{
  "version": 2,
  "contentHash": "W8SShKZ3bMvO2OzwPQj9BfdXnwgQTivs8lKtRIBcrgqKhY/ylNG0JLmGz6BTYDqe89+USnAot6H0/s1ZGC0eTw==",
  "source": "https://api.nuget.org/v3/index.json"
}

This specific version was restored by only the NuGet.org endpoint as indicated by its contentHash and source properties. We can easily verify that it came directly from NuGet.org at any time with this information.

Get Started

Let’s take the NuGetPackageExplorer repository for example. Once we restore the packages via an IDE or dotnet restore command, we will be ready to use the tool in full.

With the tool already installed, we can run the following command to generate a new NuGet.config file with the appropriate source mappings to get us started with our onboarding to the feature:

packagesourcemapper generate nuget.config

When we open the newly generated nugetPackageSourceMapping.config file, we will now see a complete mapping of our packages and their respective sources.

<packageSourceMapping>
  <packageSource key="NuGet CI packages">
    <package pattern="microsoft.*" />
    <package pattern="nuget.jobs.common" />
    …
    <package pattern="nugetgallery.core" />
    <package pattern="strathweb.cacheoutput.webapi2.strongname" />
  </packageSource>
  <packageSource key="dotnet-tools">
    <package pattern="microsoft.*" />
  </packageSource>
  <packageSource key="BuildPackages">
    <package pattern="nuget.common" />
    <package pattern="nuget.configuration" />
    …
    <package pattern="nuget.protocol" />
    <package pattern="nuget.versioning" />
  </packageSource>
  <packageSource key="nuget.org">
    <package pattern="antlr" />
    <package pattern="appinsights.windowsdesktop" />
    …
    <package pattern="xunit" />
    <package pattern="xunit.*" />
  </packageSource>
</packageSourceMapping>

This gives you the foundation of mapping each of your sources more appropriately to the ideal source you’d like it to come from. One best practice for this feature is to map a single package to a single source in a 1:1 relationship. This tool will do its best to provide you the best security practices such as complete package ID patterns and using wildcard (*) globs where appropriate.

For further instructions on using this tool or getting started with it, please visit the NuGet.PackageSourceMapper package on NuGet.org.

Closing

You’ve learned how to quickly map your NuGet packages to sources to secure your software supply chain.

For more information on using this feature, please see our documentation on package source mapping.

For more tips and tricks on how to further secure your software with NuGet, check out our documentation on best practices for a secure software supply chain.

Feedback

Your feedback is important to us. If there are any problems with this tool, check our GitHub Issues. For new issues within this experience, please report a GitHub Issue.

4 comments

Leave a comment

  • Mark Adamson

    The command output says this:

    from solution/project’s nuget.config file or global packages folder

    but it seems that it currently needs a nuget.config path passed in, so the second option isn’t currently possible. Hope that can be fixed as we tend to use a common user level nuget.config across our devs.

    • Erick YondonMicrosoft employee

      Thank for your feedback.
      Use of user level nuget.config is not ideal for this tool, I’ll add clarification later about it’s better to have solution level nuget.config. We encourage having solution level nuget.config in addition to user level config, because usually each repo has own source and need own packagesourcemapping rule. If we add packagesourcemapping rule at user level config then it’ll affect all repos which may not be what you want, in long run it’s hard to manage rules.

      Thanks,
      Erick.