Nuget restore on Docker from private feed

2.4k Views Asked by At

I have my application defined by this Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build

COPY ["MyCertificate.cer", "/usr/local/share/ca-certificates/cacert.crt"]
RUN update-ca-certificates

WORKDIR /src
COPY ["nuget.config", "MyApplication.API/"]
COPY ["MyApplication.API/MyApplication.API.csproj", "MyApplication.API/"]
RUN dotnet restore --configfile MyApplication.API/nuget.config MyApplication.API/MyApplication.API.csproj -v d

COPY . .
WORKDIR "/src/MyApplication.API"
RUN dotnet build "MyApplication.API.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "MyApplication.API.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyApplication.API.dll"]

this is my nuget.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
    <add key="MY-PRIVATE-FEED" value="https://my.private.repository.net/collections/_packaging/MY-PRIVATE-FEED/nuget/v3/index.json" />
  </packageSources>
    <config>
        <add key="signatureValidationMode" value="accept" />
    </config>
  <packageSourceCredentials>
    <MY-PRIVATE-FEED>
        <add key="Username" value="valerielinc" />
        <add key="ClearTextPassword" value="myPATtokenGeneratedFromAzureDevOps" />
    </MY-PRIVATE-FEED>
  </packageSourceCredentials>
    <trustedSigners>
        <author name="MY-PRIVATE-FEED">
            <certificate fingerprint="ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" hashAlgorithm="SHA256" allowUntrustedRoot="true" />
        </author>
        <repository name="MY-PRIVATE-FEED" serviceIndex="https://my.private.repository.net/collections/_packaging/MY-PRIVATE-FEED/nuget/v3/index.json">
            <certificate fingerprint="ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" hashAlgorithm="SHA256" allowUntrustedRoot="true" />
            <owners>ownerfeed</owners>
        </repository>
    </trustedSigners>
</configuration>

when I try to restore my project that contains 1 package that is coming from my private feed I have this error:

error :   The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot 

Stacktrace:

1>/usr/share/dotnet/sdk/5.0.400/NuGet.targets(131,5): error : Unable to load the service index for source https://my.private.repository.net/collections/_packaging/MY-PRIVATE-FEED/nuget/v3/index.json. [/src/MyApplication.API/MyApplication.API.csproj]
#17 2.778 /usr/share/dotnet/sdk/5.0.400/NuGet.targets(131,5): error :   The SSL connection could not be established, see inner exception. [/src/MyApplication.API/MyApplication.API.csproj]
#17 2.778 /usr/share/dotnet/sdk/5.0.400/NuGet.targets(131,5): error :   The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot [/src/MyApplication.API/MyApplication.API.csproj]
#17 2.789            OK https://api.nuget.org/v3-flatcontainer/microsoft.applicationinsights.aspnetcore/index.json 123ms
#17 2.797          NuGet.Protocol.Core.Types.FatalProtocolException: Unable to load the service index for source https://my.private.repository.net/collections/_packaging/MY-PRIVATE-FEED/nuget/v3/index.json.
#17 2.797           ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
#17 2.797           ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid because of errors in the certificate chain: UntrustedRoot
#17 2.797             at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception)
#17 2.797             at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
#17 2.797             at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
#17 2.797             --- End of inner exception stack trace ---
#17 2.797             at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
#17 2.797             at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
#17 2.797             at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
#17 2.797             at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
#17 2.797             at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
#17 2.798             at System.Net.Http.AuthenticationHelper.SendWithAuthAsync(HttpRequestMessage request, Uri authUri, Boolean async, ICredentials credentials, Boolean preAuthenticate, Boolean isProxyAuth, Boolean doRequestAuth, HttpConnectionPool pool, CancellationToken cancellationToken)
#17 2.798             at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
#17 2.799             at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
#17 2.799             at NuGet.Protocol.ServerWarningLogHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
#17 2.799             at NuGet.Protocol.HttpSourceAuthenticationHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
#17 2.799             at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
#17 2.799             at NuGet.Protocol.HttpRetryHandler.<>c__DisplayClass2_1.<<SendAsync>b__0>d.MoveNext()
#17 2.799          --- End of stack trace from previous location ---
#17 2.799             at NuGet.Protocol.TimeoutUtility.StartWithTimeout[T](Func`2 getTask, TimeSpan timeout, String timeoutMessage, CancellationToken token)
#17 2.799             at NuGet.Protocol.HttpRetryHandler.SendAsync(HttpRetryHandlerRequest request, String source, ILogger log, CancellationToken cancellationToken)
#17 2.800             at NuGet.Protocol.HttpSource.GetThrottledResponse(Func`1 requestFactory, TimeSpan requestTimeout, TimeSpan downloadTimeout, Int32 maxTries, Boolean isRetry, Boolean isLastAttempt, Guid sessionId, ILogger log, CancellationToken cancellationToken)
#17 2.800             at NuGet.Protocol.HttpSource.<>c__DisplayClass15_0`1.<<GetAsync>b__0>d.MoveNext()
#17 2.800          --- End of stack trace from previous location ---
#17 2.800             at NuGet.Common.ConcurrencyUtilities.ExecuteWithFileLockedAsync[T](String filePath, Func`2 action, CancellationToken token)
#17 2.800             at NuGet.Common.ConcurrencyUtilities.ExecuteWithFileLockedAsync[T](String filePath, Func`2 action, CancellationToken token)
#17 2.801             at NuGet.Protocol.HttpSource.GetAsync[T](HttpSourceCachedRequest request, Func`2 processAsync, ILogger log, CancellationToken token)
#17 2.801             at NuGet.Protocol.ServiceIndexResourceV3Provider.GetServiceIndexResourceV3(SourceRepository source, DateTime utcNow, ILogger log, CancellationToken token)
#17 2.801             --- End of inner exception stack trace ---
#17 2.801             at NuGet.Protocol.ServiceIndexResourceV3Provider.GetServiceIndexResourceV3(SourceRepository source, DateTime utcNow, ILogger log, CancellationToken token)
#17 2.801             at NuGet.Protocol.ServiceIndexResourceV3Provider.TryCreate(SourceRepository source, CancellationToken token)
#17 2.801             at NuGet.Protocol.Core.Types.SourceRepository.GetResourceAsync[T](CancellationToken token)
#17 2.801             at NuGet.Protocol.Core.Types.SourceRepository.GetResourceAsync[T]()
#17 2.801             at NuGet.Protocol.HttpFileSystemBasedFindPackageByIdResourceProvider.TryCreate(SourceRepository sourceRepository, CancellationToken token)
#17 2.802             at NuGet.Protocol.Core.Types.SourceRepository.GetResourceAsync[T](CancellationToken token)
#17 2.802             at NuGet.Protocol.Core.Types.SourceRepository.GetResourceAsync[T]()
#17 2.802             at NuGet.Commands.SourceRepositoryDependencyProvider.EnsureResource()
#17 2.802             at NuGet.Commands.SourceRepositoryDependencyProvider.FindLibraryCoreAsync(LibraryRange libraryRange, SourceCacheContext cacheContext, ILogger logger, CancellationToken cancellationToken)
#17 2.802             at NuGet.Commands.SourceRepositoryDependencyProvider.<>c__DisplayClass19_0.<<FindLibraryAsync>b__0>d.MoveNext()
#17 2.803          --- End of stack trace from previous location ---
#17 2.803             at NuGet.Commands.SourceRepositoryDependencyProvider.FindLibraryAsync(LibraryRange libraryRange, NuGetFramework targetFramework, SourceCacheContext cacheContext, ILogger logger, CancellationToken cancellationToken)
#17 2.803             at NuGet.DependencyResolver.ResolverUtility.<>c__DisplayClass9_1.<<FindLibraryFromSourcesAsync>b__0>d.MoveNext()
#17 2.803          --- End of stack trace from previous location ---
#17 2.804             at NuGet.DependencyResolver.ResolverUtility.FindLibraryFromSourcesAsync(LibraryRange libraryRange, IEnumerable`1 providers, Func`2 action)
#17 2.804             at NuGet.DependencyResolver.ResolverUtility.FindLibraryByVersionAsync(LibraryRange libraryRange, NuGetFramework framework, IEnumerable`1 providers, SourceCacheContext cacheContext, ILogger logger, CancellationToken token)
#17 2.805             at NuGet.DependencyResolver.ResolverUtility.FindPackageLibraryMatchAsync(LibraryRange libraryRange, NuGetFramework framework, IEnumerable`1 remoteProviders, IEnumerable`1 localProviders, SourceCacheContext cacheContext, ILogger logger, CancellationToken cancellationToken)
#17 2.805             at NuGet.DependencyResolver.ResolverUtility.FindLibraryMatchAsync(LibraryRange libraryRange, NuGetFramework framework, String runtimeIdentifier, IEnumerable`1 remoteProviders, IEnumerable`1 localProviders, IEnumerable`1 projectProviders, IDictionary`2 lockFileLibraries, SourceCacheContext cacheContext, ILogger logger, CancellationToken cancellationToken)
#17 2.806             at NuGet.DependencyResolver.ResolverUtility.FindLibraryEntryAsync(LibraryRange libraryRange, NuGetFramework framework, String runtimeIdentifier, RemoteWalkContext context, CancellationToken cancellationToken)
#17 2.806             at NuGet.DependencyResolver.RemoteDependencyWalker.CreateGraphNode(LibraryRange libraryRange, NuGetFramework framework, String runtimeName, RuntimeGraph runtimeGraph, Func`2 predicate, GraphEdge`1 outerEdge, TransitiveCentralPackageVersions transitiveCentralPackageVersions)
#17 2.806             at NuGet.DependencyResolver.RemoteDependencyWalker.CreateGraphNode(LibraryRange libraryRange, NuGetFramework framework, String runtimeName, RuntimeGraph runtimeGraph, Func`2 predicate, GraphEdge`1 outerEdge, TransitiveCentralPackageVersions transitiveCentralPackageVersions)
#17 2.807             at NuGet.DependencyResolver.RemoteDependencyWalker.WalkAsync(LibraryRange library, NuGetFramework framework, String runtimeIdentifier, RuntimeGraph runtimeGraph, Boolean recursive)
#17 2.807             at NuGet.Commands.ProjectRestoreCommand.WalkDependenciesAsync(LibraryRange projectRange, NuGetFramework framework, String runtimeIdentifier, RuntimeGraph runtimeGraph, RemoteDependencyWalker walker, RemoteWalkContext context, CancellationToken token)
#17 2.807             at NuGet.Commands.ProjectRestoreCommand.TryRestoreAsync(LibraryRange projectRange, IEnumerable`1 frameworkRuntimePairs, NuGetv3LocalRepository userPackageFolder, IReadOnlyList`1 fallbackPackageFolders, RemoteDependencyWalker remoteWalker, RemoteWalkContext context, Boolean forceRuntimeGraphCreation, CancellationToken token, TelemetryActivity telemetryActivity, String telemetryPrefix)
#17 2.807             at NuGet.Commands.RestoreCommand.ExecuteRestoreAsync(NuGetv3LocalRepository userPackageFolder, IReadOnlyList`1 fallbackPackageFolders, RemoteWalkContext context, CancellationToken token, TelemetryActivity telemetryActivity)
#17 2.808             at NuGet.Commands.RestoreCommand.ExecuteAsync(CancellationToken token)
#17 2.808             at NuGet.Commands.RestoreRunner.ExecuteAsync(RestoreSummaryRequest summaryRequest, CancellationToken token)
#17 2.808             at NuGet.Commands.RestoreRunner.ExecuteAndCommitAsync(RestoreSummaryRequest summaryRequest, CancellationToken token)
#17 2.808             at NuGet.Commands.RestoreRunner.CompleteTaskAsync(List`1 restoreTasks)
#17 2.809             at NuGet.Commands.RestoreRunner.RunAsync(IEnumerable`1 restoreRequests, RestoreArgs restoreContext, CancellationToken token)
#17 2.809             at NuGet.Commands.RestoreRunner.RunAsync(RestoreArgs restoreContext, CancellationToken token)
#17 2.809             at NuGet.Build.Tasks.BuildTasksUtility.RestoreAsync(DependencyGraphSpec dependencyGraphSpec, Boolean interactive, Boolean recursive, Boolean noCache, Boolean ignoreFailedSources, Boolean disableParallel, Boolean force, Boolean forceEvaluate, Boolean hideWarningsAndErrors, Boolean restorePC, Boolean cleanupAssetsForUnsupportedProjects, ILogger log, CancellationToken cancellationToken)
#17 2.810             at NuGet.Build.Tasks.RestoreTask.ExecuteAsync(ILogger log)
#17 2.811        Done executing task "RestoreTask" -- FAILED.

it looks like that the certificate added into

/usr/local/share/ca-certificates/

it's not recognized. I have tried also different locations:

  • /usr/share/ca-certificates/
  • /etc/ssl/certs/ca-certificates/

but it does not work.

The certificate that I am using (MyCertificate.cer) I have exported from Chrome and added into my application project tree. The fingerprint into the nuget.config it's also the one that I could see checking the certificate properties.

2

There are 2 best solutions below

0
On

you need to install the root CA that signed your private Nuget repository public SSL certificate in the container.

PAY ATTENTION 1 make sure that the certificate that you're trying to add to the container (the one that signed your private repository public certificate with) is the one you extract from chrome and save to the container.

PAY ATTENTION 2 also notice that some distributions may need a specific certificate format and so you might need to also convert your .cer file to .crt format (they basically have the same data but are a bit different nevertheless ). Some explanation and here's an example on how to convert the between the files.

To do so for your container (which uses Debian GNU/Linux 10 (buster)) you need to:

  1. copy the rootCA to /usr/local/share/ca-certificates/
  2. run in the container update-ca-certificates
0
On

For those who still encounter this issue, in my case I was able to resolve it in a similar way, but without using the update-ca-certificates command, since it was not working for me. Here is what I did:

COPY ["downloaded-from-browser.pem", "/usr/local/share/ca-certificates/"]
RUN cat /usr/local/share/ca-certificates/downloaded-from-browser.pem >> /etc/ssl/certs/ca-certificates.crt