Skip to content

Enable HTTP Sink with aws sigv4 auth mode only#6747

Merged
kkondaka merged 3 commits into
opensearch-project:mainfrom
kkondaka:httpsink
Apr 14, 2026
Merged

Enable HTTP Sink with aws sigv4 auth mode only#6747
kkondaka merged 3 commits into
opensearch-project:mainfrom
kkondaka:httpsink

Conversation

@kkondaka

@kkondaka kkondaka commented Apr 9, 2026

Copy link
Copy Markdown
Collaborator

Description

Enable HTTP Sink with aws sigv4 auth mode only.
Modified HTTP sink code to use only aws auth mode only.
Removed other auth options

Issues Resolved

Resolves #[Issue number to be closed when this PR is merged]

Check List

  • [ X] New functionality includes testing.
  • New functionality has a documentation issue. Please link to it in this PR.
    • New functionality has javadoc added
  • [ X] Commits are signed with a real name per the DCO

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: Kondaka <krishkdk@amazon.com>
@github-actions

github-actions Bot commented Apr 9, 2026

Copy link
Copy Markdown

✅ License Header Check Passed

All newly added files have proper license headers. Great work! 🎉

@dlvenable dlvenable left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice improvement @kkondaka . It will be good to get this sink ready to use! I have a number of suggestions. Overall we should be sure this is a generic sink and not so tightly coupled with AWS/SigV4.

One alternative is to create an aws_http sink. But I think some code clean up will make that unnecessary.

Comment thread data-prepper-plugins/http-sink/build.gradle Outdated
private PluginModel codec;

@JsonProperty("http_method")
private HTTPMethodOptions httpMethod = HTTPMethodOptions.POST;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems worth keeping.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I thought about it but since we are not using now, decided to keep it out. We can always add things that are needed back when they are needed.

}

public HttpEndPointResponse send(final byte[] payload) {
HttpEndPointResponse response = null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's also rename this class to HttpEndpointResponse since this is a single word - "endpoint."


import com.fasterxml.jackson.annotation.JsonProperty;

public class BasicAuthCredentials {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think removing a lot of the authentication options is good. But we should at least support basic auth. Otherwise nobody can use this other than with AWS. If we start here, we can look for community contributions for expanded support.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should also support unauthenticated requests.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Requests are unauthenticated when "aws:" is not used. There is already integration tests that shows that path works.


SdkHttpFullRequest signRequest(final SdkHttpFullRequest unsignedRequest) {
if (credentialsProvider == null || credentialsProvider.resolveCredentials() == null) {
return null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we fail to load credentials this will give an NPE, right? We should have a better way to fail.


private SdkHttpFullRequest createSdkHttpRequest(final String url, @Nonnull final byte[] payload) {
final SdkHttpFullRequest.Builder builder = SdkHttpFullRequest.builder()
.method(SdkHttpMethod.POST)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be configurable. It is an easy config to offer.

Also, this and the URI should be provided by the HttpSinkSender and then used by the suggested decorator. That is, don't mix the concerns of determining the method/URI with the concern of signing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed. But do not need it initially. I will do it in a follow-up PR

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we can add additional configurations later. But we shouldn't leave the code in a state where two things that don't need to be connected are. Specifically having the AWS SDK code in HttpSinkSender. Let's just decouple that and we should be good to go.


public class HttpSinkSender {
private static final Logger LOG = LoggerFactory.getLogger(HttpSinkSender.class);
private static final String HTTP_METHOD = "post";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this is unused.

}


if (config.getCustomHeaderOptions() != null) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the Codecs should ideally offer a MIME type interface.

Optional<String> getMimeType();

Then the codec can provide a default MIME type to use in the Content-Type header.

This would work well for the json codec.

However it might not work for all. I think ND-JSON doesn't have a MIME type. Maybe application/jsonl or application/x-ndjson. We should still override it with custom headers.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Let's look at this in a follow-up PR

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yea, that's good.

this.estimatedSize = calculateSize(event, codec, codecContext);
}

private long calculateSize(final Event event, final OutputCodec codec, final OutputCodecContext codecContext) throws IOException {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The event is serialized once in calculateSize() for size estimation, then again in flush() for actual sending. Consider caching the serialized bytes from the size calculation and reusing them during flush, or using a cheaper estimation like event.toJsonString().length()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this is a known issue. We cannot use event.toJsonString().length() because the codec is not always json.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

One way to improve this is to store the OutputStream from calculateSize() and reuse it in flush(), not sure if that would work. But something to look into in future.

Signed-off-by: Kondaka <krishkdk@amazon.com>

@dlvenable dlvenable left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Two things before merging:

  • Let's require the service_name because this is a generic http sink that should be able to send to any AWS SigV4 service. It isn't just for API Gateway.
  • Let's remove the AWS code from HttpSinkSender. This way if the community wants to extend the authentication options there is no need to extract this AWS code which isn't tested in an integration environment. This will give more confidence.

Signed-off-by: Kondaka <krishkdk@amazon.com>
@JsonProperty("connection_timeout")
private Duration connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;

@JsonProperty("aws_sigv4_service_name")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we have an aws: block? If so, I think we can just make this service_name under that block. We can follow on with this change or discuss further before the PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There is an aws block. Would be better to move this under that

}

@Override
public boolean isReady() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Doesn't have to be in this PR but would be good to consider implementing graceful shutdown where we flush everything in the sink before exiting.

@kkondaka kkondaka merged commit 2ef318d into opensearch-project:main Apr 14, 2026
109 of 121 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants