Surprises

TIL, TIFO or “I was today years old when”

Universal markers of new information. But it shouldn’t have been new. Documentation had been created.

I can tell you, the surprise was monumental.

In the olden days – if you ran a dotnet project without specifying UseUrls() or other tricks for local development, the containerised application would listen to ports 80 and 443.

Hence the default Dockerfile generated in some existing .NET projects will contain the rows EXPOSE 80 and EXPOSE 443. All of a sudden these two commands are completely useless, as the app quietly instead listen to ports 8080 and 8081 respectively, meaning you are exposing a port that nothing listens to.

The purpose behind the change of default port is to enable increased security. A non-root user cannot listen to ports below 1024(?) and can be set up with file access restrictions that add an additional layer of security, preventing a user from some actions even if they somehow gain entry to the website worker process.
You are still free to ignore the security benefits and keep running your website as root, but unless you take action, your docker-based apps will fail after you upgrade.

Alternatives

Embrace change – Run container as low level user

You need to change the Dockerfile to expose the ports the app listens to, so add EXPOSE statements allowing docker to map your ports. You also need to add the instruction USER app in the last bit of the Dockerfile to make sure the container will run as that user.

Of course, since the container now exposes ports 8080 and 8081 instead, you must map whatever runtime environment you are using, such as ACA configuration or ECS task definitions to take into account your non-standard ports.

Embrace change cautiously – run on new ports but as root

You need to change the Dockerfile to expose the ports the app listens to, so add EXPOSE statements allowing docker to map your ports.

Of course, since the container now exposes ports 8080 and 8081 instead, you must map whatever runtime environment you are using, such as ACA configuration or ECS task definitions to take into account your non-standard ports.

Reject change – embrace peace of mind

You can pretend like the world is a safe place and override the default ports by settings environment variables in your Dockerfile towards the end, in the final stage:

ENV ASPNETCORE_HTTP_PORTS="80,8080" ASPNETCORE_HTTPS_PORTS="443,8081"

This leaves the status quo essentially intact.

Conclusion

I suspect option 3 is the most relevant if you have existing deployments and cloud configurations where modifying port numbers is either not available to you as you would hae needed to depend on another team to make a change on their own schedule- or perhaps the change to your runtime configuration would simply be prohibitively time consuming.

Due to the limited change between Option 2 and 1, it would seem silly to stop at changing port configurations without getting the security benefit of a least privilege runtime user, so I would suggest that for new projects or low complexity software estates, definitely pick option 1 and enjoy the improved security, and in other cases – go option 3 until the security benefit makes it worth spending your maintenance time making the change to non-root running.

Leave a Reply

Your email address will not be published. Required fields are marked *