-
Notifications
You must be signed in to change notification settings - Fork 100
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
MGMT-18684: Ensure that bootstrap CSR is authenticated against cluster hosts. #895
base: master
Are you sure you want to change the base?
Conversation
@paul-maidment: This pull request references MGMT-18684 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the bug to target the "4.18.0" version, but no target version was set. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository. |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: paul-maidment The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #895 +/- ##
==========================================
- Coverage 55.70% 55.45% -0.25%
==========================================
Files 15 15
Lines 3208 3226 +18
==========================================
+ Hits 1787 1789 +2
- Misses 1249 1262 +13
- Partials 172 175 +3
|
@paul-maidment: The following test failed, say
Full PR test history. Your PR dashboard. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here. |
/hold Since it's trivial to create CSRs with any hostname, this doesn't improve security |
Thank you for your response Omer. The PR is still in draft as I am contemplating how to truly solve this issue. I accept the point about this doing little to nothing to advance security as I can see that you can't be sure that the subject of the CSR is exactly the host identified. However, thinking carefully about the original request in MGMT-18684 "This means that there is a window during installation when a rogue node can join the cluster with no verification. " is partially true but we need to consider how a CSR can be registered with the cluster
This means that they
Doesn't this mean that the joining node needs to satisfy these requirements when registering the CSR? As identified in https://issues.redhat.com/browse/MGMT-18684, it's possible that the user may register a CSR for a subject that is not a node and automatically receive approval for it. Ideally we should prevent this. If so then we only really need to check in a similar fashion to how the cluster-machine-operator does already... Granted we would probably be best to forgo the "pre reboot" information gathering phase that I do in this PR and instead rely on DNS records in the cluster post reboot. |
|
What are your thoughts on this implementation here? https://github.com/openshift/cluster-machine-approver/blob/master/pkg/controller/csr_check.go#L364 The checks that we perform to ensure that the node with a specific name
Are these sufficient to prevent a rogue node from joining or do they still fall short? Is Is it still viable that an attacker with the right kind of static IP setup and timing could add a rogue node? I think maybe, but certainly a lot harder to pull off... if an attack on
This sounds like a sizeable security hole, much worse than the timing issue as if I have the |
"Pretty sure in OCP anyone is authorized to create CSRs, this is how completely novel nodes without any credentials or information about the cluster are able to create CSRs that allow them to join. CSR approvals are the only line of defense we have against rogue nodes fully joining the cluster as far as my understanding goes" I have tried various ways of using curl requests to create and list CSR's as an anonymous user, pretty sure that I am using the correct syntax (which oc will quite happily dump for you if you add a parameter like
I receive similar messages for creation attempts also. It seems that there is not an "anonymous" way to create a CSR over HTTPS, I could be mistaken but I think we should check this in detail. Do you know who might be able to verify this? One of the Node team perhaps? These requests are being made against the "minimal" control plane that is created just before the bootstrap joins. |
Not sure, seems rather insufficient. But it depends on the requirements for cluster-machine-approver and their threat model, I can't comment on the security of that component without having this context. I can however comment on assisted-installer, which is supposed to be a user-friendly installer, not meant for power users, so the security requirements should be tight and fool-proof or come with a ton of UI warnings to help users protect themselves from our non-ideal behavior. Of course your PR is not making anything worse, but if we're pretending to fix our security posture with regards to how we choose to approve CSRs, we should actually do that right and not use some weak measures like comparing easily fakeable fields on a CSR. I don't get the point of that.
What does "Resolveable to an IP" mean here? If you're referring to the IP from which the request to create the CSR came from, then that definitely makes life harder for an attacker. But I'm not sure that information is even available outside of audit logs. If you're referring to the IP addresses specified in the CSR itself, anyone can set those to anything arbitrarily as far as I'm aware, just like they can set the hostname.
It gives you a kubeconfig, not an admin kubeconfig. It's basically a YAML with a URL in it
There must be some way to do it, as this is what the kubelet on fresh nodes with 0 credentials does (all they have is RHCOS + the trivially publicly available ignition they got from MCS), so you're probably missing something. |
44e6955
to
2685d0d
Compare
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.
Very cool
2685d0d
to
eb9f37f
Compare
eb9f37f
to
052d853
Compare
052d853
to
843614d
Compare
Issues go stale after 90d of inactivity. Mark the issue as fresh by commenting If this issue is safe to close now please do so with /lifecycle stale |
Stale issues rot after 30d of inactivity. Mark the issue as fresh by commenting If this issue is safe to close now please do so with /lifecycle rotten |
/remove-lifecycle stale |
Once the minimal control plane has been performed and consists of two nodes, we start the assisted-installer-controller pod and then reboot the bootstrap when this is ready. The bootstrap will attempt to join the control plane when it boots up. As part of this process, CSR's are submitted. Presently, we just assume that these are meant to be signed and blindly approve them.
This is problematic from a security perspective and could lead to an attack where, with careful timing, someone might be able to add a rogue node to the cluster. To prevent this, we should check that the hostname being presented in the CSR actually matches one of our known hosts.
To do this, requires two steps:
1: Prior to start of the assisted-installer-controller pod, we will save a list of known hosts in a config map called
known-hosts
, this will contain a single entrycontent
which will be a newline separated list of hostnames2: During the CSR validation, this will be read and used to verify that the CSR originates from a known host