Deploying to Azure Web Sites using NuGet package restore from a secured feed

5 minute read

Update: This post pre-dates NuGet v2.7 which changed the NuGet package restore flow (it is now by default no longer part of the MSBuild process, but runs before the MSBuild process starts).
The method explained below might no longer work and you'll need to upgrade your projects to the new NuGet package restore mechanism.
To do so:

  1. Strip out the NuGet.targets file from your project(s)
  2. Remove the .nuget folder (you can keep it but it's no longer needed)
  3. Add this NuGet.config file into the path where your solution file resides:
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <packageSources>
        <add key="Feed name" value="https://www.myget.org/F/feed_goes_here/api/v2/" />
      </packageSources>
      <activePackageSource>
        <add key="All" value="(Aggregate source)" />
      </activePackageSource>
    </configuration>
    


Original post:

Windows Azure Web Sites has this great feature to automate deployments from various source code repositories, such as Team Foundation Service, Codeplex, GitHub, DropBox, BitBucket or a local Git repository. A popular support request we receive at MyGet is the following one: "I have this web site in my hosted source code repository. How can I auto-deploy my web site and have it restore my NuGet packages from my private MyGet feed?" This is quite a common scenario. This post will focus on the set up of having a private GitHub repository and a private MyGet feed.

Creating & configuring the Azure Web Site for auto-deployment from GitHub

I have a private GitHub repository containing the CloudSurvey sample web application from the Azure Toolkit. It requires a Sql database so I'll set up Windows Azure Sql Database in one go as well. This is a breeze really: walk through the following screenies: next – next – next – finish.

Understanding the Deployment Workflow

When you connect your Windows Azure Web Site to GitHub, a post-commit hook will be created and connect the GitHub repository with a newly created remote on Windows Azure. As soon as someone pushes changes to the GitHub repository, this post-commit hook will be called and inform the Kudu service about this event. Kudu will in turn do its magic in order to build and deploy the web site.

NuGet Package Restore

Kudu takes care of the build and deployment fase. It fetches the changes linked to the commit that triggered the service, and prepares a local working environment. If your project is configured to use NuGet package restore, then this will happen in a pre-build step. It is key to understand that NuGet package restore by default is executed as part of the MSBuild process. At least, that's how it works today.

When you enable NuGet package restore on your solution, it downloads NuGet.targets (MSBuild), NuGet.exe and a NuGet.config. It also registers the NuGet.targets and some default settings into the project files that consume NuGet packages. Taking a closer look at the NuGet.targets file will reveal that a pre-build step is configured to call nuget.exe install on the packages.config file for the project being build. This install command is actually the restore command for the NuGet packages consumed by the project. It is configurable and documented. In fact: so is the NuGet.config file!

For the purpose of this post, I'll disable the default NuGet.org endpoint and redirect package restore to my private MyGet feed. The private MyGet feed requires basic authentication, so I'll need my MyGet credentials (you can set them in your MyGet user profile). The API key is not needed as that one's only required when pushing to the feed.

Creating the private MyGet feed is just another walk in the park.

Next, you'll need to adjust the NuGet configuration to point to this package source. Open the $(SolutionDir).nuget\nuget.targets file and make sure you have disabled the check for package restore consent:

<!-- Determines if package restore consent is required to restore packages -->
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">false</RequireRestoreConsent>

You also need to configure the MyGet private feed to be used as the one and only package source. Open your local nuget.config file and edit it to something as shown below. Note that I'm using the new ClearTextPassword capabilities in the latest dev-build (yeay, pull request accepted!):

Because by default NuGet encrypts feed credentials using machine specific information, these encrypted credentials are not portable. There's no way to encrypt them on-the-fly on WAWS:

  • the Kudu process does not have write permissions on the global nuget.config
  • if you use the new –ConfigFile option to store the encrypted credentials in your local nuget.config, it will fail as well because the Kudu process runs with impersonation enabled or without loading the user profile

I've got another accepted pull-request to add the –StorePasswordInClearText option to the nuget.exe sources command, so you should be able to run the following in the future as well:

nuget.exe sources add –Name <feedname> -User <username> -Password <password> -ConfigFile nuget.config -StorePasswordInClearText

One last thing: adjust the RestoreCommand in your nuget.targets file to the following:

<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -NonInteractive $(RequireConsentSwitch) -solutionDir "$(SolutionDir) "</RestoreCommand>

And that's it: you should be up and running now. Your build log should contain the following trace:

1>  Using credentials from config. UserName: xavierdecoster

One last tip in case you hit any issues or you need more information to debug: all nuget.exe commands support a –verbosity switch, so simply add –verbosity detailed at the end of the commands in the nuget.targets file to get more verbose output. Can't wait for the v2.5 release :-)

How's that secure?!

Exactly... For now: clear text is the only supported credential format. I'd love to see a new section in the WAWS Management portal though: nuget.config overrides. Similar to how you can secure your storage credentials or other web.config settings. Assuming the default convention of $(SolutionDir)\.nuget\nuget.config, it cannot be that hard to build?

As for the credentials to use: you should use an account with limited permissions for package restore. At MyGet you can easily create an account with only read-access on your NuGet repository. Please do that and use that one instead of your admin account! Also, if you don't want people to get access to your private feed, simply use a private GitHub or BitBucket repository.

Anyway, many thanks to the NuGet team for the new -ConfigFile command option, and for hinting into sending another PR to add the -StorePasswordInClearText option as well!

Leave a Comment