@piccaso commented on Fri Mar 30 2018
Inspired by the following warning i tried to set some permissions manually:
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
Here is my Dockerfile, relevant changes are commented:
FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
ENV ASPNETCORE_URLS="http://*:8080" # Cange to 8080 because 80 requires elevated privileges
EXPOSE 8080
FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
ENV CONFIGURATION=Debug
COPY <solution>.sln ./
COPY <project>/<project>.csproj <project>/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/<project>
RUN dotnet build -c $CONFIGURATION /p:Docker=true -o /app
FROM build AS publish
RUN dotnet publish -c $CONFIGURATION /p:Docker=true -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
## run as www-data(33), readonly
RUN chown -R 33:33 ./
RUN chmod -R 0500 ./
RUN chmod -R 0700 *.dll # if the dll's are not writeable, it won't start
USER 33
ENTRYPOINT ["dotnet", "<project>.dll"]
When I run it, it seems to work, but there are some warnings:
> docker run --rm -p 8080:8080 -it <name>
realpath(): Permission denied
realpath(): Permission denied
warn: Microsoft.AspNetCore.DataProtection.Repositories.EphemeralXmlRepository[50]
Using an in-memory repository. Keys will not be persisted to storage.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[59]
Neither user profile nor HKLM registry available. Using an ephemeral key repository. Protected data will be unavailable when application exits.
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
No XML encryptor configured. Key {9a31e777-4bc3-4884-83bb-1f9be653bdd4} may be persisted to storage in unencrypted form.
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:8080
How can I find out what the two realpath() errors are about and how can i address the other warnings?
And why can't the dll's be read only - I would prefer them not to change once containerized.
This is still an experiment for me and i don't feel like putting it in production that way, so i would not mind changing to 2.1 if it would solve some problems (and wait even longer to go into production).
Thx!
@MichaelSimons commented on Tue Apr 03 2018
@piccaso - This appears to be an CoreFx/ASP.NET Core specific issue that is not specific to Docker. Your Docker usage is just happening to restrict the permissions. The realpath(): Permission denied message is definitely not very helpful. I was unable to repo using the aspnetapp sample. Can you share your app or create a simple app that reproduces the issue?
@piccaso commented on Wed Apr 04 2018
I tried to apply my changes to the aspnetapp sample but it worked without any problem. Even made the /app folder completely read-only this time.
I went on an created a new WebApi project with docker support in Visual Studio (v15.6.4) and changed the Dockerfile there.
And then i got this realpath messages again.
When running within Visual Studio (F5) the output is:
realpath(): Invalid argument
realpath(): Invalid argument
realpath(): Invalid argument
When running with docker-compose up:
webapisample_1 | realpath(): Permission denied
webapisample_1 | realpath(): Permission denied
I also tried using the dotnet:2.0-* images like the aspnetapp sample does but the output stayed the same.
Here are 2 samples:
both can be started with docker-compose up.
All dll's are read-only and it still seems to work, so the requirement of having some dll's writeable is probably from a 3'd party package...
But I would really like to know what realpath is trying to access :)
Thanks for looking into this!
@MichaelSimons commented on Wed Apr 04 2018
Related to https://github.com/microsoft/dotnet/issues/294
@MichaelSimons commented on Wed Apr 11 2018
@natemcmaster - Can you investigate this and help make sure the underlying product issue is tracked/fixed?
@natemcmaster commented on Fri Apr 13 2018
My guess is that realpath() is invoked by corehost or the base netcore runtime. ASP.NET is all managed code and doesn't invoke realpath directly. @jkotas @stephentoub any ideas what might cause realpath(): Permission denied? Any good ways to trace calls to this?
@jkotas commented on Fri Apr 13 2018
Any good ways to trace calls to this?
Try strace.
@jkotas commented on Fri Apr 13 2018
The message is likely printed by the host here: https://github.com/dotnet/core-setup/blob/master/src/corehost/common/pal.unix.cpp#L525
cc @steveharter
@natemcmaster commented on Fri Apr 13 2018
Thanks Jan, that appears to be a likely culprit.
@piccaso can you try gathering a corehost trace? Enabling the trace is going to blast the console with information, so you'll need to redirect to a log file.
docker run --rm -p 8080:8080 -e COREHOST_TRACE=1 -it <name> 2>log.txt
@steveharter commented on Fri Apr 13 2018
FYI realpath() is called frequently (by the host) to convert a relative path to absolute, and to normalize the path.
@piccaso commented on Sat Apr 14 2018
@jkotas i did not manage to use strace and drop privileges but managed to do it with ltrace: ltrace log
The interesting part:
283 SYS_lstat("/root", 0x7ffcc9ed57d0) = 0
283 SYS_lstat("/root/.dotnet", 0x7ffcc9ed57d0) = -13
283 SYS_dup(2) = 4
283 SYS_fcntl(4, 3, 0x7fc56ccbaac7, 264) = 0x8002
283 SYS_fstat(4, 0x7ffcc9ed4cb0) = 0
283 SYS_write(4, "realpath(): Permission denied\n", 30) = 30
283 SYS_close(4) = 0
283 SYS_stat("/root/.dotnet/store/x64/netcorea"..., 0x7ffcc9ed5808) = -13
283 SYS_lstat("/root", 0x7ffcc9ed57d0) = 0
283 SYS_lstat("/root/.nuget", 0x7ffcc9ed57d0) = -13
283 SYS_dup(2) = 4
283 SYS_fcntl(4, 3, 0x7fc56ccbaac7, 0x7fc56cef2b58) = 0x8002
283 SYS_fstat(4, 0x7ffcc9ed4cb0) = 0
283 SYS_write(4, "realpath(): Permission denied\n", 30) = 30
sorry @natemcmaster, i did not see you message... that was much easier than using ltrace.
But 2>log.txt does not work in powershell and I don`t know how to do it so here ist the complete output: corehost trace
Runtime config [/app/WebApiSample.runtimeconfig.json] is valid=[1]
realpath(): Permission denied
Ignoring host interpreted additional probing path /root/.dotnet/store/x64/netcoreapp2.0 as it does not exist.
realpath(): Permission denied
Ignoring host interpreted additional probing path /root/x64/netcoreapp2.0ges as it does not exist.
Ignoring host interpreted additional probing path /usr/share/dotnet/sdk/NuGetFax64/netcoreapp2.0 as it does not exist.
--- Resolving FX directory, specified ''
Searching FX directory in [/usr/share/dotnet/]
and later on:
Changing Selected FX version from [] to [/usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.6]
Chose FX version [/usr/share/dotnet/shared/Microsoft.NETCore.App/2.0.6]
looks like it all turns out well :)
Can I assume that the realpath(): Permission denied messages can be ignored?
Or ist there any way i could persuade dotnet to not poke around in root's home?
@natemcmaster commented on Tue Apr 17 2018
Thanks for the logs @piccaso. It sounds to me like this issue belongs on https://github.com/dotnet/core-setup.
I assume this is not expected in 2.1, as the bar is pretty high at this point.
Any updates on this?
@vitek-karas any chance this could be addressed in 3.0? The realpath() messages are confusing to users that run into it. We had a user that (incorrectly) published their application with a dev runtime config that caused the host to probe locations that it didn't have access to (the build was done as root and the application runs as non-root in the container; thus /root directories ended up in the dev runtime config and the host printed the realpath() errors).
I'd prefer the host not emit any messages that aren't fatal errors or actionable warnings since the user has no idea where the message is coming from (is it me? is it ASP.NET? is it the framework?). I think this would be fine as a verbose message, especially considering it's not really up to the PAL to define what's an error not, I would assume.
@peterhuene There's a fix for this in dotnet/core-setup#7133. It doesn't change behavior (won't print the realpath() errors while probing paths, though), so it's very likely it's going to be addressed in 3.0. :crossed_fingers:
Most helpful comment
@peterhuene There's a fix for this in dotnet/core-setup#7133. It doesn't change behavior (won't print the
realpath()errors while probing paths, though), so it's very likely it's going to be addressed in 3.0. :crossed_fingers: