Skip to content
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

Add connectToNodeAsExtension in TransportService #6866

Merged
merged 8 commits into from Apr 28, 2023

Conversation

cwperks
Copy link
Member

@cwperks cwperks commented Mar 29, 2023

Description

Companion PR in sdk repo: opensearch-project/opensearch-sdk-java#619
Companion PR in security repo: opensearch-project/security#2599

Adds new methods inside TransportService for extension to connect to opensearch as an extension. When performing the handshake for security, the extension needs to identify itself as an extension. This PR is modeled after cross cluster functionality where the node identifies which cluster it belongs to using the _opendistro_security_remotecn ThreadContext header, for this PR I chose to have the extension identify its request using the extension_unique_id thread context header which the security plugin needs to permit the handshake and other transport requests used in extension bootstrap process.

Check List

  • New functionality includes testing.
    • All tests pass
  • New functionality has been documented.
    • New functionality has javadoc added
  • Commits are signed per the DCO using --signoff
  • Commit changes are listed out in CHANGELOG.md file (See: Changelog)

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Signed-off-by: Craig Perkins <cwperx@amazon.com>
@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

  • RESULT: UNSTABLE ❕
  • TEST FAILURES:
      2 org.opensearch.backwards.MixedClusterClientYamlTestSuiteIT.test {p0=indices.shrink/30_copy_settings/Copy settings during shrink index}

Signed-off-by: Craig Perkins <cwperx@amazon.com>
@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@codecov-commenter
Copy link

codecov-commenter commented Mar 31, 2023

Codecov Report

Merging #6866 (5ebed1c) into main (d984f50) will decrease coverage by 0.10%.
The diff coverage is 69.35%.

📣 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    #6866      +/-   ##
============================================
- Coverage     70.71%   70.61%   -0.10%     
+ Complexity    59497    59456      -41     
============================================
  Files          4859     4859              
  Lines        285339   285369      +30     
  Branches      41133    41135       +2     
============================================
- Hits         201772   201517     -255     
- Misses        66965    67303     +338     
+ Partials      16602    16549      -53     
Impacted Files Coverage Δ
...ava/org/opensearch/transport/TransportService.java 79.12% <0.00%> (-3.39%) ⬇️
...a/org/opensearch/index/mapper/TextFieldMapper.java 88.62% <100.00%> (+0.27%) ⬆️

... and 458 files with indirect coverage changes

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

Signed-off-by: Craig Perkins <cwperx@amazon.com>
@github-actions
Copy link
Contributor

github-actions bot commented Apr 3, 2023

Gradle Check (Jenkins) Run Completed with:

  • RESULT: UNSTABLE ❕
  • TEST FAILURES:
      1 org.opensearch.cluster.allocation.AwarenessAllocationIT.testThreeZoneOneReplicaWithForceZoneValueAndLoadAwareness

Copy link
Member

@saratvemulapalli saratvemulapalli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to understand. It definitely makes sense for cross cluster use cases. But with connectToNodeAsExtension lying in OpenSearch node, who is the intended user ?

Also curious how security is plugged in for cross cluster. I couldnt map the flow.

@cwperks
Copy link
Member Author

cwperks commented Apr 10, 2023

Hi @saratvemulapalli, from what I can tell in the code. For cross-cluster use-cases, the security plugin enriches all outgoing transport requests with the cluster name:

When receiving the request, the Security plugin first confirms if the request is coming from a trusted node by comparing the distinguished name from the node to the full list of node_dns:

If its coming from a trusted node, it then goes on to compare the cluster name that the node belongs to:


With the method (connectToNodeAsExtension ) added here, I proposed adding a threadcontext header extension_unique_id on the handshake with the OpenSearch node.

The call to extensionTransportService.connectToNode(extensionsRunner.opensearchNode); in ExtensionsInitRequestHandler will not succeed with the security plugin installed because it initiates a transport handshake action which the security plugin forbids since it originates from outside the cluster.

The companion Security plugin PR checks for the extensions_unique_id threadcontext header and permits the request as coming from a trusted source even though it is not a node in the cluster.

Thank you for reviewing this! I wanted to get a PR out to show the problem with secure communication between OpenSearch nodes and an extension to get more eyes on the problem.

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

) {
return (newConnection, actualProfile, listener) -> {
// We don't validate cluster names to allow for CCS connections.
threadPool.getThreadContext().putHeader("extension_unique_id", extensionUniqueId);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the line that makes this different than connectToNode. This injects extension_unique_id into the threadcontext for the handshake which allows the security plugin to identify that the transport request was initiated by an extensions. See companion PR in security repo: opensearch-project/security#2599

Copy link
Contributor

@scrawfor99 scrawfor99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

) {
return (newConnection, actualProfile, listener) -> {
// We don't validate cluster names to allow for CCS connections.
threadPool.getThreadContext().putHeader("extension_unique_id", extensionUniqueId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused on how using the thread context will work here. The action futures are all going to be working asynchronously so how can we inject to the thread context at this point?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to model this like cross-cluster which uses a thread context header to store the cluster name. See: https://github.com/opensearch-project/security/blob/main/src/main/java/org/opensearch/security/transport/SecurityInterceptor.java#L131-L132

With this, during the handshake it would inject the extension_unique_id into the context so that the security plugin can know which extension the handshake originated from.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses the getTransportInterceptors extension point from NetworkPlugin to send and restore the thread context from one node to another. As far as I know, something like this would not be supported with extensions.

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@saratvemulapalli
Copy link
Member

Hi @saratvemulapalli, from what I can tell in the code. For cross-cluster use-cases, the security plugin enriches all outgoing transport requests with the cluster name:

When receiving the request, the Security plugin first confirms if the request is coming from a trusted node by comparing the distinguished name from the node to the full list of node_dns:

If its coming from a trusted node, it then goes on to compare the cluster name that the node belongs to:

With the method (connectToNodeAsExtension ) added here, I proposed adding a threadcontext header extension_unique_id on the handshake with the OpenSearch node.

The call to extensionTransportService.connectToNode(extensionsRunner.opensearchNode); in ExtensionsInitRequestHandler will not succeed with the security plugin installed because it initiates a transport handshake action which the security plugin forbids since it originates from outside the cluster.

The companion Security plugin PR checks for the extensions_unique_id threadcontext header and permits the request as coming from a trusted source even though it is not a node in the cluster.

Thank you for reviewing this! I wanted to get a PR out to show the problem with secure communication between OpenSearch nodes and an extension to get more eyes on the problem.

Thanks @cwperks , this really helps.

@saratvemulapalli
Copy link
Member

The changes are good, could you take care of gradle check.

@github-actions
Copy link
Contributor

Gradle Check (Jenkins) Run Completed with:

@cwperks
Copy link
Member Author

cwperks commented Apr 28, 2023

@saratvemulapalli The CI is passing now.

@saratvemulapalli saratvemulapalli merged commit b752555 into opensearch-project:main Apr 28, 2023
8 checks passed
@owaiskazi19 owaiskazi19 added the backport 2.x Backport to 2.x branch label May 1, 2023
@opensearch-trigger-bot
Copy link
Contributor

The backport to 2.x failed:

The process '/usr/bin/git' failed with exit code 128

To backport manually, run these commands in your terminal:

# Fetch latest updates from GitHub
git fetch
# Create a new working tree
git worktree add ../.worktrees/backport-2.x 2.x
# Navigate to the new working tree
pushd ../.worktrees/backport-2.x
# Create a new branch
git switch --create backport/backport-6866-to-2.x
# Cherry-pick the merged commit of this pull request and resolve the conflicts
git cherry-pick -x --mainline 1 b752555d38477b7077aacb4b8a15b07877299b0c
# Push it to GitHub
git push --set-upstream origin backport/backport-6866-to-2.x
# Go back to the original working tree
popd
# Delete the working tree
git worktree remove ../.worktrees/backport-2.x

Then, create a pull request where the base branch is 2.x and the compare/head branch is backport/backport-6866-to-2.x.

cwperks added a commit to cwperks/OpenSearch that referenced this pull request May 1, 2023
…6866)

* Add connectToNodeAsExtension in TransportService

Signed-off-by: Craig Perkins <cwperx@amazon.com>

* Add to CHANGELOG

Signed-off-by: Craig Perkins <cwperx@amazon.com>

* Update java docstrings

Signed-off-by: Craig Perkins <cwperx@amazon.com>

---------

Signed-off-by: Craig Perkins <cwperx@amazon.com>
(cherry picked from commit b752555)
owaiskazi19 pushed a commit that referenced this pull request May 1, 2023
* Add connectToNodeAsExtension in TransportService (#6866)

* Add connectToNodeAsExtension in TransportService

Signed-off-by: Craig Perkins <cwperx@amazon.com>

* Add to CHANGELOG

Signed-off-by: Craig Perkins <cwperx@amazon.com>

* Update java docstrings

Signed-off-by: Craig Perkins <cwperx@amazon.com>

---------

Signed-off-by: Craig Perkins <cwperx@amazon.com>
(cherry picked from commit b752555)

* Update CHANGELOG

Signed-off-by: Craig Perkins <cwperx@amazon.com>

---------

Signed-off-by: Craig Perkins <cwperx@amazon.com>
shiv0408 pushed a commit to Gaurav614/OpenSearch that referenced this pull request Apr 25, 2024
…6866)

* Add connectToNodeAsExtension in TransportService

Signed-off-by: Craig Perkins <cwperx@amazon.com>

* Add to CHANGELOG

Signed-off-by: Craig Perkins <cwperx@amazon.com>

* Update java docstrings

Signed-off-by: Craig Perkins <cwperx@amazon.com>

---------

Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Shivansh Arora <hishiv@amazon.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport 2.x Backport to 2.x branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants