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 withDefaultHeaders to connection configuration for ElasticsearchIO #25024

Merged
merged 3 commits into from
Jan 18, 2023

Conversation

EgbertW
Copy link

@EgbertW EgbertW commented Jan 16, 2023

Addresses #25018

This PR adds a withDefaultHeaders setting to the ElasticsearchIO ConnectionConfiguration. This allows you to provide any type of org.apache.http.Header instead of sticking to the built-in ApiKey and Bearer headers supported already. In a way, their functionality could be implemented using this option instead if desirable.

This addresses #25018 - it allows to create a custom class implementing org.apache.http.Header that manages the bearer token lifecycle and use this with ElasticsearchIO - this all without imposing any specifics in the ElasticsearchIO library.


Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:

  • Mention the appropriate issue in your description (for example: addresses #123), if applicable. This will automatically add a link to the pull request in the issue. If you would like the issue to automatically close on merging the pull request, comment fixes #<ISSUE NUMBER> instead.
  • Update CHANGES.md with noteworthy changes.
  • If this contribution is large, please file an Apache Individual Contributor License Agreement.

See the Contributor Guide for more tips on how to make review process smoother.

To check the build health, please visit https://github.com/apache/beam/blob/master/.test-infra/BUILD_STATUS.md

GitHub Actions Tests Status (on master branch)

Build python source distribution and wheels
Python tests
Java tests
Go tests

See CI.md for more information about GitHub Actions CI.

@github-actions
Copy link
Contributor

Assigning reviewers. If you would like to opt out of this review, comment assign to next reviewer:

R: @apilloud for label java.
R: @Abacn for label io.

Available commands:

  • stop reviewer notifications - opt out of the automated review tooling
  • remind me after tests pass - tag the comment author after tests pass
  • waiting on author - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)

The PR bot will only process comments in the main thread (not review comments).

@egalpin
Copy link
Member

egalpin commented Jan 16, 2023

Thanks @EgbertW ! To fix up the spotless linter check, you can run ./gradlew spotlessApply from the project root on your machine; that will auto-fix any style issues which can then be committed.

I noticed also that there are unit test failures due to compilation failures. You can run tests locally by running one of the ES test suites like ./gradlew --info :sdks:java:io:elasticsearch-tests:elasticsearch-tests-7:test to confirm that there are no more failures 😊

@@ -514,6 +521,8 @@ public ConnectionConfiguration withApiKey(String apiKey) {

/**
* If Elasticsearch authentication is enabled, provide a bearer token.
* Be aware that you can only use one of {@Code withApiToken()}, {@code withBearerToken()} and
* {@code withDefaultHeaders} at the same time, as they will override eachother.
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reasonable way to add Precondition checks to try to alert the user when these mutually exclusive fields have been used in conjunction?

Copy link
Author

Choose a reason for hiding this comment

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

There is but I didn't add it because the same issue was already lurking with just withApiKey and withBearerToken. I added checks to all three methods now to check that only one is used at a time - see my last update.

@egalpin
Copy link
Member

egalpin commented Jan 16, 2023

I'm not denying the utility here, but I'm not 100% clear on how this addresses #25018. Could you elaborate on how this technique can be used to work with short-lived credentials?

@EgbertW
Copy link
Author

EgbertW commented Jan 17, 2023

I'm not denying the utility here, but I'm not 100% clear on how this addresses #25018. Could you elaborate on how this technique can be used to work with short-lived credentials?

Of course. What I did to work with short-lived tokens is create a new header class, something resembling:

class OauthTokenHeader extends BasicHeader {
    OIDCIDToken accessToken;

    ...

    @Override
    public String getValue() {
        if (accessToken.isExpired()) {
            accessToken.renew();
        }
        return String.format("Bearer %s", accessToken.getToken());
    }
}

Since the Elasticsearch RestClient will add the defaultHeaders on each outgoing request, it will invoke getValue on every request, giving the opportunity to check if the token has expired and if so, renew it.

@EgbertW
Copy link
Author

EgbertW commented Jan 17, 2023

Thanks @EgbertW ! To fix up the spotless linter check, you can run ./gradlew spotlessApply from the project root on your machine; that will auto-fix any style issues which can then be committed.

I noticed also that there are unit test failures due to compilation failures. You can run tests locally by running one of the ES test suites like ./gradlew --info :sdks:java:io:elasticsearch-tests:elasticsearch-tests-7:test to confirm that there are no more failures 😊

Ah, that is helpful. I just did and fixed the formatting and the compile error - I was using a newer feature that isn't available in Java 8.

@egalpin
Copy link
Member

egalpin commented Jan 17, 2023

I'm not denying the utility here, but I'm not 100% clear on how this addresses #25018. Could you elaborate on how this technique can be used to work with short-lived credentials?

Of course. What I did to work with short-lived tokens is create a new header class, something resembling:

class OauthTokenHeader extends BasicHeader {
    OIDCIDToken accessToken;

    ...

    @Override
    public String getValue() {
        if (accessToken.isExpired()) {
            accessToken.renew();
        }
        return String.format("Bearer %s", accessToken.getToken());
    }
}

Since the Elasticsearch RestClient will add the defaultHeaders on each outgoing request, it will invoke getValue on every request, giving the opportunity to check if the token has expired and if so, renew it.

Aha! Very nice 😊 I think this kind of detail might be non-obvious to many users who might want to accomplish the same. Could you please add this example to the docstring for withDefaultHeader as an example for how someone might use it?

@EgbertW
Copy link
Author

EgbertW commented Jan 18, 2023

I'm not denying the utility here, but I'm not 100% clear on how this addresses #25018. Could you elaborate on how this technique can be used to work with short-lived credentials?

Of course. What I did to work with short-lived tokens is create a new header class, something resembling:

class OauthTokenHeader extends BasicHeader {
    OIDCIDToken accessToken;

    ...

    @Override
    public String getValue() {
        if (accessToken.isExpired()) {
            accessToken.renew();
        }
        return String.format("Bearer %s", accessToken.getToken());
    }
}

Since the Elasticsearch RestClient will add the defaultHeaders on each outgoing request, it will invoke getValue on every request, giving the opportunity to check if the token has expired and if so, renew it.

Aha! Very nice 😊 I think this kind of detail might be non-obvious to many users who might want to accomplish the same. Could you please add this example to the docstring for withDefaultHeader as an example for how someone might use it?

I just updated the PR with this example added to the docstring.

Copy link
Member

@egalpin egalpin left a comment

Choose a reason for hiding this comment

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

Thanks @EgbertW ! I’ll merge after all the workflows pass, which I expect them to 😊 Hopefully this can make the 2.45.0 cut scheduled for today!

@egalpin egalpin added this to the 2.45.0 Release milestone Jan 18, 2023
@egalpin egalpin merged commit b50b801 into apache:master Jan 18, 2023
@EgbertW
Copy link
Author

EgbertW commented Jan 19, 2023

Thanks @EgbertW ! I’ll merge after all the workflows pass, which I expect them to 😊 Hopefully this can make the 2.45.0 cut scheduled for today!

Thanks for merging! Looking forward to seeing it in the next release :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants