Search code examples
azuredockerazure-devopsnugetdockerfile

Azure Devops nuget artifact feed and docker


Is there a good way to create an authentication mechanism to Devops to be able to access the artifact NuGet feed? I would like to create a base image for my team that would allow them to just pull an image from our Azure Container Registry that has access to our devops nuget feed. Ideally people wouldn't have to have the same stock dockerfile code in every single project that grabs a PAT from their host build system. This would also allow us to CICD this a little more nicely.

My current solution

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app

ARG IT_PAT
ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS "{\"endpointCredentials\": [{\"endpoint\": \"https://pkgs.dev.azure.com/MNPIT/_packaging/MNP/nuget/v3/index.json\",\"username\": \"build\",\"password\": \"${IT_PAT}\"}]}"
RUN mkdir -p $HOME/.nuget/plugins
WORKDIR /deps

# Downloads and installs the NuGet credential plugin so we can login to the private NuGet feed
RUN curl https://github.com/microsoft/artifacts-credprovider/releases/download/v0.1.24/Microsoft.NetCore2.NuGet.CredentialProvider.tar.gz -L -o creds.tar.gz -s
RUN tar -xzf creds.tar.gz
RUN cp -r plugins/netcore/ ~/.nuget/plugins
  • Stock code in every build file
  • Each user configuring their environment variables with a PAT
  • Passing the PAT on every build
  • Does not work with an automated build system

Solution

  • I would like to create a base image for my team that would allow them to just pull an image from our Azure Container Registry that has access to our devops nuget feed.

    You can include the credentials inside your image to achieve this, But for security concern, you've better add some extra steps or codes to pass the credentials from outside the image.

    Based on your current solution, you can use the system predefined variable $(System.AccessToken) to get the security token in the azure devops CICD pipeline. Then in the docker build task, you pass the access token to the ARG IT_PAT as arguement,

    --build-arg IT_PAT=$(System.AccessToken)

    Besides using the NuGet credential plugin, You can also use the dotnet cli to add credentials to the nuget source. And then pass the $(System.AccessToken) in the build arguements. See below:

    ARG PAT
    COPY . .
    RUN dotnet nuget add source "your-source-url" --name "source-name" --username "useless" --password "$PAT" --store-password-in-clear-text
    RUN dotnet restore
    

    Another workaround is to include the nuget.config in the build context. But you need to include a nuget.config file without the credentials first, and then add an extra nuget task to add the credentials to the config file. Then copy the nuget.config in your docker file . See below:

    Add a nuget task to run below custom command to add the credentials to the nuget.config file.

    sources Add -Name "MyPackages" -Source "https://my.pkgs.visualstudio.com/_packaging/MyPackages/nuget/v3/index.json" -username any -password $(System.AccessToken) -ConfigFile Source/Nuget.config -StorePasswordInClearText
    

    Copy the nuget.config in the docker file, Donot forget to delete the nuget.config file when the restore is complete:

    COPY *.csproj .
    COPY ./nuget.config .
    RUN dotnet restore
    RUN rm nuget.config
    

    If you are using Yaml based pipeline. You can also check out container jobs. Then you use your private container by setting up the container endpoints. And then you can directly use the restore tasks in your pipeline. See below example, the nuget restore task will run in your private container, and it can access to your azure feeds directly by specifying attribute vstsFeed to your nuget feed:

    When you specify a container in your pipeline, the agent will first fetch and start the container. Then, each step of the job will run inside the container.

    container:
      image: myprivate/registry:ubuntu1604
      endpoint: private_dockerhub_connection
    
    steps:
    - task: NuGetCommand@2
      inputs:
        command: 'restore'
        feedsToUse: 'select'
        vstsFeed: 'my-azure-nuget-feed'
        restoreSolution: '**/*.sln'
    

    For more information you can check out this thread.