-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support HTTP Basic authentication on the HTTP source plugin. This use…
…s the plugin framework to provide the authentication so that it can be customized without having to change the HTTP Source plugin itself. Resolves #464 Signed-off-by: David Venable <[email protected]>
- Loading branch information
Showing
16 changed files
with
363 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
dependencies { | ||
implementation project(':data-prepper-api') | ||
implementation 'com.linecorp.armeria:armeria:1.9.2' | ||
testImplementation 'com.linecorp.armeria:armeria-junit5:1.9.2' | ||
} |
27 changes: 27 additions & 0 deletions
27
...ain/java/com/amazon/dataprepper/armeria/authentication/ArmeriaAuthenticationProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.amazon.dataprepper.armeria.authentication; | ||
|
||
import com.linecorp.armeria.server.ServerBuilder; | ||
|
||
/** | ||
* An interface for providing authentication in Armeria-based HTTP servers. | ||
* <p> | ||
* Plugin authors can use this interface for Armeria authentication in | ||
* HTTP servers. | ||
* | ||
* @since 1.2 | ||
*/ | ||
public interface ArmeriaAuthenticationProvider { | ||
/** | ||
* The plugin name for the plugin which allows unauthenticated | ||
* requests. This plugin will disable authentication. | ||
*/ | ||
String UNAUTHENTICATED_PLUGIN_NAME = "unauthenticated"; | ||
|
||
/** | ||
* Adds an authentication decorator to an Armeria {@link ServerBuilder}. | ||
* | ||
* @param serverBuilder the builder for the server needing authentication | ||
* @since 1.2 | ||
*/ | ||
void addAuthenticationDecorator(ServerBuilder serverBuilder); | ||
} |
30 changes: 30 additions & 0 deletions
30
...ain/java/com/amazon/dataprepper/armeria/authentication/HttpBasicAuthenticationConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.amazon.dataprepper.armeria.authentication; | ||
|
||
import com.fasterxml.jackson.annotation.JsonCreator; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
|
||
/** | ||
* Configuration for HTTP Basic Authentication. | ||
* | ||
* @since 1.2 | ||
*/ | ||
public class HttpBasicAuthenticationConfig { | ||
private final String username; | ||
private final String password; | ||
|
||
@JsonCreator | ||
public HttpBasicAuthenticationConfig( | ||
@JsonProperty("username") final String username, | ||
@JsonProperty("password") final String password) { | ||
this.username = username; | ||
this.password = password; | ||
} | ||
|
||
public String getUsername() { | ||
return username; | ||
} | ||
|
||
public String getPassword() { | ||
return password; | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
.../src/main/java/com/amazon/dataprepper/plugins/HttpBasicArmeriaAuthenticationProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.amazon.dataprepper.plugins; | ||
|
||
import com.amazon.dataprepper.armeria.authentication.ArmeriaAuthenticationProvider; | ||
import com.amazon.dataprepper.armeria.authentication.HttpBasicAuthenticationConfig; | ||
import com.amazon.dataprepper.model.annotations.DataPrepperPlugin; | ||
import com.amazon.dataprepper.model.annotations.DataPrepperPluginConstructor; | ||
import com.linecorp.armeria.server.HttpService; | ||
import com.linecorp.armeria.server.ServerBuilder; | ||
import com.linecorp.armeria.server.auth.AuthService; | ||
|
||
import java.util.Objects; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.function.Function; | ||
|
||
/** | ||
* The plugin for HTTP Basic authentication of Armeria servers. | ||
* | ||
* @since 1.2 | ||
*/ | ||
@DataPrepperPlugin(name = "http_basic", | ||
pluginType = ArmeriaAuthenticationProvider.class, | ||
pluginConfigurationType = HttpBasicAuthenticationConfig.class) | ||
public class HttpBasicArmeriaAuthenticationProvider implements ArmeriaAuthenticationProvider { | ||
|
||
private final HttpBasicAuthenticationConfig httpBasicAuthenticationConfig; | ||
|
||
@DataPrepperPluginConstructor | ||
public HttpBasicArmeriaAuthenticationProvider(final HttpBasicAuthenticationConfig httpBasicAuthenticationConfig) { | ||
Objects.requireNonNull(httpBasicAuthenticationConfig); | ||
Objects.requireNonNull(httpBasicAuthenticationConfig.getUsername()); | ||
Objects.requireNonNull(httpBasicAuthenticationConfig.getPassword()); | ||
this.httpBasicAuthenticationConfig = httpBasicAuthenticationConfig; | ||
} | ||
|
||
@Override | ||
public void addAuthenticationDecorator(final ServerBuilder serverBuilder) { | ||
serverBuilder.decorator(createDecorator()); | ||
} | ||
|
||
private Function<? super HttpService, ? extends HttpService> createDecorator() { | ||
return AuthService.builder() | ||
.addBasicAuth((context, basic) -> | ||
CompletableFuture.completedFuture( | ||
httpBasicAuthenticationConfig.getUsername().equals(basic.username()) && | ||
httpBasicAuthenticationConfig.getPassword().equals(basic.password()))) | ||
.newDecorator(); | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...ain/java/com/amazon/dataprepper/plugins/UnauthenticatedArmeriaAuthenticationProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.amazon.dataprepper.plugins; | ||
|
||
import com.amazon.dataprepper.armeria.authentication.ArmeriaAuthenticationProvider; | ||
import com.amazon.dataprepper.model.annotations.DataPrepperPlugin; | ||
import com.linecorp.armeria.server.ServerBuilder; | ||
|
||
/** | ||
* The plugin to use for unauthenticated access to Armeria servers. It | ||
* disables authentication on endpoints. | ||
* | ||
* @since 1.2 | ||
*/ | ||
@DataPrepperPlugin(name = ArmeriaAuthenticationProvider.UNAUTHENTICATED_PLUGIN_NAME, pluginType = ArmeriaAuthenticationProvider.class) | ||
public class UnauthenticatedArmeriaAuthenticationProvider implements ArmeriaAuthenticationProvider { | ||
@Override | ||
public void addAuthenticationDecorator(final ServerBuilder serverBuilder) { | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
.../test/java/com/amazon/dataprepper/plugins/HttpBasicArmeriaAuthenticationProviderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package com.amazon.dataprepper.plugins; | ||
|
||
import com.amazon.dataprepper.armeria.authentication.HttpBasicAuthenticationConfig; | ||
import com.linecorp.armeria.client.WebClient; | ||
import com.linecorp.armeria.common.AggregatedHttpResponse; | ||
import com.linecorp.armeria.common.HttpResponse; | ||
import com.linecorp.armeria.common.HttpStatus; | ||
import com.linecorp.armeria.common.auth.BasicToken; | ||
import com.linecorp.armeria.server.ServerBuilder; | ||
import com.linecorp.armeria.testing.junit5.server.ServerExtension; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.RegisterExtension; | ||
|
||
import java.util.UUID; | ||
|
||
import static org.hamcrest.CoreMatchers.equalTo; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.reset; | ||
import static org.mockito.Mockito.when; | ||
|
||
class HttpBasicArmeriaAuthenticationProviderTest { | ||
|
||
private static final String USERNAME = UUID.randomUUID().toString(); | ||
private static final String PASSWORD = UUID.randomUUID().toString(); | ||
|
||
@RegisterExtension | ||
static ServerExtension server = new ServerExtension() { | ||
@Override | ||
protected void configure(final ServerBuilder sb) { | ||
sb.service("/test", (ctx, req) -> HttpResponse.of(200)); | ||
|
||
final HttpBasicAuthenticationConfig config = mock(HttpBasicAuthenticationConfig.class); | ||
when(config.getUsername()).thenReturn(USERNAME); | ||
when(config.getPassword()).thenReturn(PASSWORD); | ||
new HttpBasicArmeriaAuthenticationProvider(config).addAuthenticationDecorator(sb); | ||
} | ||
}; | ||
|
||
@Nested | ||
class ConstructorTests { | ||
private HttpBasicAuthenticationConfig config; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
config = mock(HttpBasicAuthenticationConfig.class); | ||
|
||
} | ||
|
||
private HttpBasicArmeriaAuthenticationProvider createObjectUnderTest() { | ||
return new HttpBasicArmeriaAuthenticationProvider(config); | ||
} | ||
|
||
@Test | ||
void constructor_with_null_Config_throws() { | ||
config = null; | ||
assertThrows(NullPointerException.class, this::createObjectUnderTest); | ||
} | ||
|
||
@Test | ||
void constructor_with_null_username_throws() { | ||
reset(config); | ||
when(config.getPassword()).thenReturn(UUID.randomUUID().toString()); | ||
assertThrows(NullPointerException.class, this::createObjectUnderTest); | ||
} | ||
|
||
@Test | ||
void constructor_with_null_password_throws() { | ||
reset(config); | ||
when(config.getUsername()).thenReturn(UUID.randomUUID().toString()); | ||
assertThrows(NullPointerException.class, this::createObjectUnderTest); | ||
} | ||
} | ||
|
||
@Nested | ||
class WithServer { | ||
@Test | ||
void httpRequest_without_authentication_responds_Unauthorized() { | ||
final WebClient client = WebClient.of(server.httpUri()); | ||
|
||
final AggregatedHttpResponse httpResponse = client.get("/test").aggregate().join(); | ||
|
||
assertThat(httpResponse.status(), equalTo(HttpStatus.UNAUTHORIZED)); | ||
} | ||
|
||
@Test | ||
void httpRequest_with_incorrect_authentication_responds_Unauthorized() { | ||
final WebClient client = WebClient.builder(server.httpUri()) | ||
.auth(BasicToken.of(UUID.randomUUID().toString(), UUID.randomUUID().toString())) | ||
.build(); | ||
|
||
final AggregatedHttpResponse httpResponse = client.get("/test").aggregate().join(); | ||
|
||
assertThat(httpResponse.status(), equalTo(HttpStatus.UNAUTHORIZED)); | ||
} | ||
|
||
@Test | ||
void httpRequest_with_correct_authentication_responds_OK() { | ||
final WebClient client = WebClient.builder(server.httpUri()) | ||
.auth(BasicToken.of(USERNAME, PASSWORD)) | ||
.build(); | ||
|
||
final AggregatedHttpResponse httpResponse = client.get("/test").aggregate().join(); | ||
|
||
assertThat(httpResponse.status(), equalTo(HttpStatus.OK)); | ||
} | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
...java/com/amazon/dataprepper/plugins/UnauthenticatedArmeriaAuthenticationProviderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.amazon.dataprepper.plugins; | ||
|
||
import com.linecorp.armeria.client.WebClient; | ||
import com.linecorp.armeria.common.AggregatedHttpResponse; | ||
import com.linecorp.armeria.common.HttpResponse; | ||
import com.linecorp.armeria.common.HttpStatus; | ||
import com.linecorp.armeria.common.auth.BasicToken; | ||
import com.linecorp.armeria.server.ServerBuilder; | ||
import com.linecorp.armeria.testing.junit5.server.ServerExtension; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.RegisterExtension; | ||
|
||
import java.util.UUID; | ||
|
||
import static org.hamcrest.CoreMatchers.equalTo; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
|
||
class UnauthenticatedArmeriaAuthenticationProviderTest { | ||
@RegisterExtension | ||
static ServerExtension server = new ServerExtension() { | ||
@Override | ||
protected void configure(final ServerBuilder sb) { | ||
sb.service("/test", (ctx, req) -> HttpResponse.of(200)); | ||
new UnauthenticatedArmeriaAuthenticationProvider().addAuthenticationDecorator(sb); | ||
} | ||
}; | ||
|
||
@Test | ||
void httpRequest_without_authentication_responds_OK() { | ||
final WebClient client = WebClient.of(server.httpUri()); | ||
|
||
final AggregatedHttpResponse httpResponse = client.get("/test").aggregate().join(); | ||
|
||
assertThat(httpResponse.status(), equalTo(HttpStatus.OK)); | ||
} | ||
|
||
@Test | ||
void httpRequest_with_BasicAuthentication_responds_OK() { | ||
final WebClient client = WebClient.builder(server.httpUri()) | ||
.auth(BasicToken.of(UUID.randomUUID().toString(), UUID.randomUUID().toString())) | ||
.build(); | ||
|
||
final AggregatedHttpResponse httpResponse = client.get("/test").aggregate().join(); | ||
|
||
assertThat(httpResponse.status(), equalTo(HttpStatus.OK)); | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...lugins/armeria-common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mock-maker-inline |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.