-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Configure IC root filesystem as read-only #3548
Conversation
Should I add tests that check whether the applied K8s pods have read-only filesystems?
I have no explicit errors on test suite, and all tests are reported as passed/skipped/warning, when running from my Windows machine. But this is strange result after tweaking the |
There is a This has potential of allowing the |
238dc80
to
cb5a48f
Compare
Pushed a new commit which configures Nginx Plus with its own different base image in respective static YAML files. |
Spun up an Ubuntu 22.04 (Jammy) VM in Azure, installed Docker and Minikube, and ran tests.
|
|
I am thinking if this is somewhat similar to trac.nginx.org#753 (Nginx leaves UNIX domain sockets after SIGQUIT). My main workstation is Windows-based - running Docker in WSL2, with K8s v1.25.4 on top. |
cb5a48f
to
a82bcd7
Compare
Cause appears to be left-over sockets after an unclean shutdown for |
Not seeing a nice way how to get a clean find /var/lib/nginx -type s -print | while read s; do
if ! grep -qF " $s" /proc/net/unix; then
entrypoint_log "$0: removing leftover socket: $s"
rm -v "$s"
fi
done If it's preferred to integrate the socket logic in this K8s repo instead of upstream Docker image, I could set it as a separate Init Container in the Deployment/DaemonSet: find /var/lib/nginx -type s -print0 | xargs -0 -I{} sh -c 'grep -qF " {}" /proc/net/unix || rm -v "{}"' What are the thoughts on this? Any better approaches that come to mind before I open a PR on that project? |
a82bcd7
to
ed69a82
Compare
@shaun-nx, how should the self-assign be interpreted in this case? Will you handle the socket cleanup? Noticed that there are new commits on |
Hi @sigv |
Sorry about any perceived delays. The team is heads down on some existing work and we will take a more serious look as soon as we can guarantee some focus time. |
All good - thank you for the update! Hopefully all the active tasks go smoothly 🙏🏻 I will circle back around to this PR in two weeks, just to check on the availability of involved team members. |
ed69a82
to
3a0c643
Compare
Interesting CI failure on Nginx Plus:
Doubt there is something suddenly wrong with the PR that would be relevant. Is something up with |
3a0c643
to
81d2a66
Compare
Codecov Report
📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more @@ Coverage Diff @@
## main #3548 +/- ##
==========================================
+ Coverage 52.21% 52.24% +0.03%
==========================================
Files 59 59
Lines 16877 16873 -4
==========================================
+ Hits 8812 8816 +4
+ Misses 7768 7762 -6
+ Partials 297 295 -2 see 2 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
ff4cb0f
to
45a545f
Compare
885668d
to
1d3af4f
Compare
Hi @sigv just wanted to keep you posted. Sorry that it has been taking a bit of time to do re-testing on this PR. Some additional internal work has required my focus. I should have an update for you tomorrow. Thanks for your patience 🙏 |
Thanks for the update! I'm just keeping the PR rebased and without merge conflicts in the meantime 🙂 |
73d246b
to
bb17a8e
Compare
The Nginx Ingress Controller has various protections against attacks, such as running the service as non-root to avoid changes to files. An additional industry best practice is having root filesystems set as read-only so that the attack surface is further reduced by limiting changes to binaries and libraries. This commit ensures such a defense in depth is enabled for the Nginx Ingress Controller. To accomplish read-only rootfs, we will create emptyDir Volumes for - `/etc/nginx` - `/var/cache/nginx` - `/var/lib/nginx` - `/var/log/nginx` We populate `/etc` mount with an Init Container, as there are generic configuration files here. If the base image is updated via Helm chart, then Init Container will pull files from the new base image. The other three empty volumes are populated during runtime, as they are not expected to have valuable files as part of base image: - `/var/cache` mount will be used in case caching is enabled. - `/var/lib` is used for some sockets and temporary files. - `/var/log` is used for logging in the default configuration. By default, the emptyDir will be persisted as long as the Pod is not disposed of. Simple Pod crashes will retain the data. There is no maximum size limit implemented currently, but may be added at some point in time as a further protection. For improved performance, cache could be moved to ram tmpfs as well (currently backed by disk). Do note, the initial commit does not set read-only root filesystem as default. Instead, this is an opt-in feature available on the chart. Users of non-Helm YAML manifests need to manually uncomment the aforementioned volumes and initContainers. Co-authored-by: Shaun <[email protected]>
bb17a8e
to
a10301e
Compare
And I feel stupid about my 're-review' button dropping others again. Sorry! 😐 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks all good to me. Thanks again for this work @sigv 🚀
Although: the potential issue of nginx being killed/dying still stands. It could leave a socket file behind that is no longer used. This would block new nginx process start-up. I wonder if this should be documented in some page - "Known issues" for release? This should be considered in the backlog as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the patience during review process @sigv, we tested upgrades from previous version with and without readOnlyFileSystem and all looks okay to me 👍🏼
@vepatel, it's a concern that crept up during my local testing. It should be all safe, but as there are more eyes on it now, wanted to highlight it. Upgrade and redeployment process should be good. The potential issue I observed is when Pod dies abruptly leaving a socket behind. That seemed similar to trac.nginx.org#753 (Nginx leaves UNIX domain sockets after SIGQUIT). KIC-813 issue title sounds promising. Looking back at it, I did not test this on older versions.. And as this PR does not impact relevant behavior, it should be reproducible on versions before this PR, if the Pod is abused there. The socket file would simply be on root filesystem, which I believe is also persisted across restarts. So the concern is most likely moot. |
Big thanks to the whole team! ❤️ Is there a calendar-based release schedule, or is it fully based on the items linked to a milestone? Asking as to understand if the official 3.1 tag is far out. |
@sigv we're targeting |
We are planning on getting better with the Milestones. (I must have not pushed an update to that milestone, whoops) |
KIC-1094
Proposed changes
The Nginx Ingress Controller has various protections against attacks, such as running the service as non-root to avoid changes to files. An additional industry best practice is having root filesystems set as read-only so that the attack surface is further reduced by limiting changes to binaries and libraries. This commit ensures such a defense in depth is enabled for the Nginx Ingress Controller.
To accomplish read-only rootfs, we will create emptyDir Volumes for
/etc/nginx
/var/cache/nginx
/var/lib/nginx
/var/log/nginx
We populate
/etc
mount with an Init Container, as there are generic configuration files here. If the base image is updated via Helm chart, then Init Container will pull files from the new base image.The other three empty volumes are populated during runtime, as they are not expected to have valuable files as part of base image:
/var/cache
mount will be used in case caching is enabled./var/lib
is used for some sockets and temporary files./var/log
is used for logging in the default configuration.By default, the emptyDir will be persisted as long as the Pod is not disposed of. Simple Pod crashes will retain the data.
There is no maximum size limit implemented currently, but may be added at some point in time as a further protection. For improved performance, cache could be moved to ram tmpfs as well (currently backed by disk).
Do note, the initial commit does not set read-only root filesystem as default. Instead, this is an opt-in feature available on the chart. Users of non-Helm YAML manifests need to manually uncomment the aforementioned volumes and initContainers.
Resolves #1677.
Checklist
Before creating a PR, run through this checklist and mark each as complete.