-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Enroll node API #72129
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
Enroll node API #72129
Conversation
Enroll node API can be used by new nodes in order to join an existing cluster that has security features enabled. The response of a call to this API contains all the necessary information that the new node requires in order to configure itself and bootstrap trust with the existing cluster.
|
Pinging @elastic/es-security (Team:Security) |
|
Just added couple comments, but will take a closer look on Monday |
API can be called by the startup process or a user with appropriate privileges while elasticsearch is in the enrollment mode to obtain an enrollment token used to enroll a new node to the cluster or configure a new client to communicate with the cluster. Resolve: elastic#71438 Related: elastic#72129
|
|
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackPlugin.java
Outdated
Show resolved
Hide resolved
… as ASN.1 DER encoded, Base64 encoded strings instead of PKCS12. PKCS12 makes sense for storage on disk, but not that much as an intermediate format for transmission
|
@elasticmachine update branch |
...n/java/org/elasticsearch/xpack/security/action/enrollment/TransportNodeEnrollmentAction.java
Outdated
Show resolved
Hide resolved
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfig.java
Show resolved
Hide resolved
client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java
Outdated
Show resolved
Hide resolved
| "cluster:admin/repository/analyze/blob", | ||
| "cluster:admin/repository/analyze/blob/read" | ||
| "cluster:admin/repository/analyze/blob/read", | ||
| NodeEnrollmentAction.NAME |
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.
Does this mean that invoking client-soon-to-be-node has to be an operator?
If it's using an API key it is not currently possible. Even if it where, it doesn't sound to useful. When we release the enroll credential we explicitly want any client with that credential to be able to use it to join the cluster.
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.
The idea is that this should not be used in ESS, even if someone is superuser or grants themselves the enroll privilege. We don't "support" operator privileges in any other circumstance, so I don't see this as a problem.
If it's using an API key it is not currently possible.
I've missed that part, will take a look
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.
Chatted a little with Yang. Wasn't aware of the API key limitation for operator only. In retrospect, we don't actually need the API keys to be operator only and since the enrollment mode settings is not going to be a dynamic one, then it can't also be operator only. I think we'd need to depend on setting the enrollment mode to false on ESS instances and not whitelist the setting so that administrators cannot overwrite it in ESS deployment settings
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.
To check that I'm following, you're proposing introducing a setting that will "enable" the enroll node API.
The setting is static and it must be false (API not available) for ESS. Am I right? Can it be false by default, so that the new startup scripts (the ones generating or consuming the enrollment tokens) have to set it to true?
I agree with the setting proposal, and we can discuss if it is static, or dynamic for operators only, as well as its default value.
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.
It doesn't have to be part of this PR, but raise an issue with your thoughts, please.
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.
We synced:
- The enrollment mode enabled setting is static ( introduced in Create enrollment token API #72186)
- The default value is false and we will be setting it to true while/when auto-generating configuration
- We're introducing a base rest handler for all enrollment APIs that check that security is enabled and that enrollment mode is enabled, and return an error if not.
- Setting wlll not be whitelisted in ESS so users won't be able to enable it.
.../main/java/org/elasticsearch/xpack/core/security/action/enrollment/NodeEnrollmentAction.java
Outdated
Show resolved
Hide resolved
|
|
||
|
|
||
| /** | ||
| * Allows a node to join to a secured cluster using the Enroll Node API. |
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.
I would highlight that this API allows the caller to stand-up a node that is able to join the secure cluster, which also means that the caller has the capacity to "impersonate" the cluster to any other clients.
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.
I'll add something to that effect. I think the most important part is to clearly call this out in the privilege description but no objection to adding information in the APIs description
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.
@albertzaharovits can you elaborate on "which also means that the caller has the capacity to "impersonate" the cluster to any other clients. " ? What specific threat do you have in mind ?
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.
An astute user might infer that this endpoint is very sensitive, given that a rogue node can siphon all the data from the cluster (even this, I think, is worth mentioning somewhere).
But it's more than this, because the caller doesn't have to join the cluster (which might be otherwise monitored, and the attacker be detected), it can use the API response to forge himself certificates that can impersonate any cluster node to a client.
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.
@albertzaharovits worth noting that an attacker needs also to be in a position to MITM legitimate clients in order to impersonate the server ( assuming that by "impersonate any node" you mean that the caller of the API can get a valid signed certificate signed by the same CA that would have signed the legitimate nodes certificates )
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.
@jkakavas One must pass an enroll token to clients to have them configured; the same enroll token that's used to register nodes. There can be an attacker that intercepts client-cluster communication.
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.
Yes that is my argument too, one needs to be MITM. I'm not trying to downplay the attack, just noting the constraints
| final List<String> nodeList = new ArrayList<>(); | ||
| for (DiscoveryNode node : clusterService.state().getNodes()) { | ||
| nodeList.add(node.getAddress().toString()); | ||
| } |
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.
What do you think if we use the output of NodeEnrollmentAction.NAME with the transport metric parameter?
It gives me more confidence that we're returning the right addresses, and the client might already be used to parsing that.
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.
I'm not sure I understood the suggestion @albertzaharovits .You mean that we should return enroll:enroll_node:192.168.1.2:9300 instead of 192.168.1.2:9300 ? What does this buy us ?
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.
Bleah... sorry, I messed up the clipboard buffers.
I meant NodeEnrollmentAction.NAME -> NodesInfoAction.NAME .
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.
Specifically, I mean that the nodes info API internally uses
elasticsearch/server/src/main/java/org/elasticsearch/transport/TransportInfo.java
Line 88 in f379216
| private String formatPublishAddressString(String propertyName, TransportAddress publishAddress) { |
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.
makes sense, I'm calling this for the enroll client API transport action, might as well do this here too, no objections
albertzaharovits
left a comment
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.
I had a couple of comments, but overall it does what it's supposed to do.
We can discuss it a bit, but we might need to polish it when all the pieces are in-place, so lets not overdo it now.
BigPandaToo
left a comment
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.
Approoving considering you address Albert's comments
|
Thanks for the round @albertzaharovits . I addressed your feedback or commented accordingly, if we could do another round on Monday before I go, that'd be awesome <3 |
x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/StoreKeyConfig.java
Outdated
Show resolved
Hide resolved
|
Provided you find resolve the remaining comments. |
|
Thanks for the round @albertzaharovits , I'll merge this if CI is green before I go, otherwise please do merge at will |
Method to be called by the startup process while elasticsearch is in the enrollment mode to obtain an enrollment token used to enroll a new node to the cluster. Resolve: elastic#71438 Related: elastic#72129
enrollment mode to obtain an enrollment token used to enroll a new node to the cluster. Resolve: elastic#71438 Related: elastic#72129
Enroll node API can be used by new nodes in order to join an
existing cluster that has security features enabled. The response
of a call to this API contains all the necessary information that
the new node requires in order to configure itself and bootstrap
trust with the existing cluster.