Avoid SecurityException in repository-S3 on DefaultS3OutputStream.flush()#25254
Conversation
… in repository-S3 plugin to avoid SecurityException by Streams.copy(). A plugin is only allowed to use its own jars when performing privileged operations. The S3 client might open a new Socket on close(). elastic#25192
|
Since this is a community submitted pull request, a Jenkins build has not been kicked off automatically. Can an Elastic organization member please verify the contents of this patch and then kick off a build manually? |
|
Thanks @joachimdraeger. I'll take a look at this. Is this the only place where this occurs? I see that we close those Maybe we should also override |
|
@elasticmachine please test this |
| }); | ||
| } | ||
|
|
||
| private void flushPriveleged(byte[] bytes, int off, int len, boolean closing) throws IOException { |
There was a problem hiding this comment.
Spelling: flushPrivileged
Hmm. Now that I look at the source for So I think your change will be sufficient. |
|
@tbrooks8 See #25206 for why we came to the approach here. |
|
I added poc code for testing socket permissions. Test fails without the fix. |
|
|
||
| private void openSocket() { | ||
| try { | ||
| Socket socket = new Socket("localhost", 9200); |
There was a problem hiding this comment.
Are there any guidelines which ports could be used in unit/integration tests? I think I wasn't able to use any other port than 9200 without changing further permissions.
|
Just found out about MockSocket, I can probably make this work nicely now. |
|
@jasontedor, I added the Socket tests and changed it to use MockSocket and a random port. I think this is in-line with similar tests now. |
|
Yes, mock socket is the way to go. I'll look closely soon. |
|
test this please |
|
Did you forget to tag elasticmachine, @jasontedor? |
|
@elasticmachine test this please |
|
@joachimdraeger No, that's not necessary. In fact, I had checked on the status of the build previously and it was green. What happened here is that the cleanup of the PR builds is quite aggressive, they only stay outstanding for a few days (to be precise, I think that it's three). Thus, the build was cleaned up sometime over the weekend and that leads to the PR status no longer showing up on the PR. Thankfully, @s1monw kicked off another build and we see here that we are still green. |
jasontedor
left a comment
There was a problem hiding this comment.
Thanks @joachimdraeger, this generally looks good but I left some more thorough comments.
| this.mockSocketPort = mockSocketPort; | ||
| } | ||
|
|
||
| // simulate a socket connection to check that SocketAccess is used correctly |
There was a problem hiding this comment.
Can you elaborate a bit more why this necessary, exactly what we are simulating here?
| // simulate a socket connection to check that SocketAccess is used correctly | ||
| private void simulateS3SocketConnection() { | ||
| try { | ||
| Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), mockSocketPort); |
There was a problem hiding this comment.
Maybe wrap this in a try-with-resources instead?
| Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), mockSocketPort); | ||
| socket.close(); | ||
| } catch (IOException e) { | ||
| throw new RuntimeException(e); |
There was a problem hiding this comment.
How about throwing UncheckedIOException instead?
| public static void openMockSocket() throws IOException { | ||
| socket = new MockServerSocket(0, 50, InetAddress.getByName("127.0.0.1")); | ||
| new Thread(() -> { | ||
| while (!socket.isClosed()) { |
There was a problem hiding this comment.
It's not obvious to me what is going on here, can you please explain?
| try { | ||
| socket.accept(); | ||
| } catch (IOException e) { | ||
| logger.log(Level.ERROR, e); |
| @BeforeClass | ||
| public static void openMockSocket() throws IOException { | ||
| socket = new MockServerSocket(0, 50, InetAddress.getByName("127.0.0.1")); | ||
| new Thread(() -> { |
There was a problem hiding this comment.
This thread can leak and fail the test, I think that you need to clean it up (join on it in tear down).
…bStoreContainerTests and further improvements.
|
Thanks for the review @jasontedor, I implemented the suggested changes and hope that the additional documentation makes it clearer. |
jasontedor
left a comment
There was a problem hiding this comment.
LGTM, I left one more request though. Did you want to take another look @tbrooks8?
| Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), mockSocketPort); | ||
| socket.close(); | ||
| try (Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), mockSocketPort)) { | ||
| Assert.assertTrue(socket.isConnected()); // NOOP to keep static analysis happy |
There was a problem hiding this comment.
We tend to static import these assert methods; would you mind doing the same here so this can only be assertTrue without the class qualifier?
There was a problem hiding this comment.
Sure, no problem
Tim-Brooks
left a comment
There was a problem hiding this comment.
I mean this all looks alright to me. I just kind of have a question about how we handle the server socket that we must open for this test.
| // Accept connections from MockAmazonS3. | ||
| mockS3ServerSocket.accept(); | ||
| } catch (IOException e) { | ||
| logger.log(Level.ERROR, e); |
There was a problem hiding this comment.
I think that this will generate an error in the logs most of the time when this test ends. As we will call close and I think accept throws an exception when the socket is closed. @jasontedor - is this alright?
There was a problem hiding this comment.
That's a good point @tbrooks8, we should not do this.
There was a problem hiding this comment.
I'll remove it
|
Thanks for the review @tbrooks8. Could you have another look? |
|
Ready to merge @jasontedor ? |
* master: Remove deprecated created and found from index, delete and bulk (elastic#25516) fix testEnsureVersionCompatibility for 5.5.0 release fix Version.v6_0_0 min compatibility version to 5.5.0 Add bwc indices for 5.5.0 Add v5_5_1 constant [DOCS] revise high level client Search Scroll API docs (elastic#25599) Improve REST error handling when endpoint does not support HTTP verb, add OPTIONS support (elastic#24437) Avoid SecurityException in repository-S3 on DefaultS3OutputStream.flush() (elastic#25254) [Tests] Add tests for CompletionSuggestionBuilder#build() (elastic#25575)
* master: (42 commits) Harden global checkpoint tracker Remove deprecated created and found from index, delete and bulk (elastic#25516) fix testEnsureVersionCompatibility for 5.5.0 release fix Version.v6_0_0 min compatibility version to 5.5.0 Add bwc indices for 5.5.0 Add v5_5_1 constant [DOCS] revise high level client Search Scroll API docs (elastic#25599) Improve REST error handling when endpoint does not support HTTP verb, add OPTIONS support (elastic#24437) Avoid SecurityException in repository-S3 on DefaultS3OutputStream.flush() (elastic#25254) [Tests] Add tests for CompletionSuggestionBuilder#build() (elastic#25575) Enable cross-setting validation [Docs] Fix typo in bootstrap-checks.asciidoc (elastic#25597) Index ids in binary form. (elastic#25352) bwc checkout should fetch from all remotes IndexingIT should check for global checkpoints regardless of master version [Tests] Add tests for PhraseSuggestionBuilder#build() (elastic#25571) Remove unused class MinimalMap (elastic#25590) [Docs] Document Scroll API for Java High Level REST Client (elastic#25554) Disable date field mapping changing (elastic#25285) Allow BWC Testing against a specific branch (elastic#25510) ...
|
Thanks for merging @tbrooks8. |
Moved SocketAccess.doPrivileged up the stack to DefaultS3OutputStream in repository-S3 plugin to avoid SecurityException by Streams.copy(). A plugin is only allowed to use its own jars when performing privileged operations. The S3 client might open a new Socket on close(). #25192