I have a yaml Azure DevOps pipeline as below which is trying to consume a nuget feed from another organization.
As you can see I am using the nugetauthenticate@1 task to create valid credentials using a Service Connection created by a user in the target organization.
I have a docker file called by the pipeline in which I install the artifacts credential provider via their sh script.
I am setting the JSON environment variable in the dockerfile with a valid PAT passed into the docker task:
arguments: '--build-arg FEED_ACCESSTOKEN=$(VSS_NUGET_ACCESSTOKEN)'
n.b. I have tried using the cred provider variable $(VSS_NUGET_ACCESSTOKEN) and by using my own pipeline variable containing a valid PAT.
When I call dotnet restore in the docker step the step faults with:
error NU1301: Unable to load the service index for source https://pkgs.dev.azure.com/{org}/_packaging/{feed}/nuget/v3/index.json
I’ve turned on verbose logging and the credential provider is using the provided configuration but I don’t get an Auth (401) issue, just an error hitting the nuget index page feed so i think its not even getting a chance to authenticate.
Any advice would be greatly appreciated.
Pipeline:
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
NUGET.PLUGIN.HANDSHAKE.TIMEOUT.IN.SECONDS: 20
NUGET.PLUGIN.REQUEST.TIMEOUT.IN.SECONDS: 20
steps:
- task: NuGetAuthenticate@1
inputs:
nuGetServiceConnections: 'nuget-feed'
- task: NodeTool@0
inputs:
versionSpec: '18.17.1'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
arguments: 'xxx/xxx.sln'
- task: Docker@2
inputs:
command: 'build'
Dockerfile: 'xxx/xxx/Dockerfile'
buildContext: 'xxx'
arguments: '--build-arg FEED_ACCESSTOKEN=$(VSS_NUGET_ACCESSTOKEN)'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
publishLocation: 'Container'
Docker file:
FROM mcr.microsoft.com/dotnet/aspnet:6.0.14-bullseye-slim-amd64 AS base
ARG FEED_ACCESSTOKEN
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:6.0.427-1-bullseye-slim-amd64 AS build
ENV NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS=60
ENV NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=60
RUN curl -L https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | sh
WORKDIR /src
COPY ["xxx/xxx.csproj", "xxx/"]
COPY ["xxx/nuget.config", "xxx/"]
ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS="{"endpointCredentials": [{"endpoint":"https://pkgs.dev.azure.com/{org}/_packaging/{feed}/nuget/v3/index.json", "username":"docker", "password":"${FEED_ACCESSTOKEN}"}]}"
RUN echo $VSS_NUGET_EXTERNAL_FEED_ENDPOINTS
RUN dotnet restore "xxx/xxx.csproj" --verbosity detailed
2
Answers
I can reproduce the same error using the Dockerfile you shared.
After checking the log, I found the password is empty in the endpointCredentials command. I added the command
RUN echo "Access Token: $FEED_ACCESSTOKEN"
to confirm it.After this, I moved the line
ARG FEED_ACCESSTOKEN
afterFROM mcr.microsoft.com/dotnet/sdk:6.0.427-1-bullseye-slim-amd64 AS build
.New Dockerfile:
This time, the password is not empty and the restore step is successful.
Cause of the issue:
ARG
variables are scoped to the stage where they are defined. So, you should move this line to the build stage where you use it.If you want to share variable in multi-stage Dockerfile, each stage must include the
ARG
instruction. You can refer this question for more information about Share variable in multi-stage Dockerfile.As shared in Miao Tian’s answer , you need to move the ARG to the correct code block in dockerfile.
Additionally, when the Nuget Authentication task authenticates resources via service connection, its output variable: VSS_NUGET_ACCESSTOKEN is not a valid PAT/Password. Therefore, it cannot be used directly to set the environment variable: VSS_NUGET_EXTERNAL_FEED_ENDPOINTS in dockerfile.
To solve this issue, you can directly pass PAT to dockerfile(e.g.
--build-arg FEED_ACCESSTOKEN=$(YourPAT)
)Or you can use another output variable: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS) from Nuget Authenticate task.
For example:
This variable is a valid feed artifacts endpoint contains password and can be directly passed to the Dockerfile for authentication.
Here is an example:
Dockerfile:
Since there is a known issue: [BUG]: Docker@2 arguments (VSS_NUGET_EXTERNAL_FEED_ENDPOINTS) without quotes when passing the variable:VSS_NUGET_EXTERNAL_FEED_ENDPOINTS via docker task, we need to change to use script/bash/powershell task to run docker command to build the image.
Pipeline Sample:
In this case, we can pass the credential from service connection to dockerfile for nuget feed authentication.
Result: