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 support for user proxy configuration #3631

Merged
merged 35 commits into from Sep 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
05ea963
Add ProxyConfiguration
conniey May 1, 2019
56b5483
Pass ProxyConfiguration through all layers.
conniey May 1, 2019
b3aa039
Expose isProxyConfigured and ctor documentation to ProxyConfiguration.
conniey May 1, 2019
fdb9a61
Adding constructor and documentation. Updating shouldUseProxy check.
conniey May 1, 2019
5490095
Adding documentation to useSystemProxyConfiguration().
conniey May 1, 2019
cf323b4
Update ProxyConfiguration to match proton-j extensions.
conniey May 8, 2019
44992a1
Fix build breaks.
conniey May 8, 2019
8fbe94a
Convert ProxyConfiguration to one exposed by proton-j extensions and …
conniey May 8, 2019
d09bc2d
Remove old overload for WebSocketProxyConnectionHandler.
conniey May 8, 2019
1354a1d
Return correct proxy address and log exception.
conniey May 8, 2019
fa48845
Adding mockito-core as a test dependency
conniey May 9, 2019
f4b10f9
Remove Objects.requireNonNull check
conniey May 9, 2019
a1596d8
Add overload for syncClient to create one with ProxyConfiguration
conniey May 9, 2019
bb2f7d7
Fix incorrect naming of constant
conniey May 9, 2019
cf10747
Use WebSocketProxyConnectionHandler when proxyConfig has address conf…
conniey May 9, 2019
a6bbf0d
Remove unused imports and add LICENSE
conniey May 9, 2019
ae0a94c
Add ProxyConfigurationTest.
conniey May 9, 2019
d6387c2
Add WebSocketProxyConnectionHandlerTest
conniey May 9, 2019
0606a60
Add WebSocketProxyConnectionHandler tests
conniey May 10, 2019
4e148f7
Adding an any() parameter.
conniey May 10, 2019
86aa79a
Update version to 1.2.1 qpid-proton-j-extensions
conniey May 13, 2019
e49067f
Add ProxyConfiguration to MessagingFactoryBuilder
conniey Aug 6, 2019
4ca5e5c
Update to use new overloads.
conniey Aug 6, 2019
57a27cc
Merge branch 'master' of https://github.com/Azure/azure-sdk-for-java …
conniey Aug 14, 2019
8c21669
Merge branch 'master' of https://github.com/Azure/azure-sdk-for-java …
conniey Aug 15, 2019
105c629
Add ProxyConfiguration to EventHubClientOptions.
conniey Aug 15, 2019
86eb9cf
Plumb ProxyConfiguration through AAD or TokenCredentials.
conniey Aug 15, 2019
de807d5
Add environment variables for Proxy Integration Test
conniey Aug 19, 2019
c4d14a0
Merge branch 'master' of https://github.com/Azure/azure-sdk-for-java …
conniey Aug 22, 2019
41ba7b7
Bump versions of parent/pom.xml
conniey Aug 22, 2019
a3a9635
Merge branch 'master' of https://github.com/Azure/azure-sdk-for-java …
conniey Aug 22, 2019
ff9ae46
Update azure-data-sdk-parent in event hubs libraries.
conniey Aug 22, 2019
094f2b3
Add mockito as dependency.
conniey Aug 22, 2019
21e243c
Bump Event Hubs version to 3.1.0
conniey Aug 22, 2019
45b43ba
Merge branch 'master' of https://github.com/Azure/azure-sdk-for-java …
conniey Sep 3, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion parent/pom.xml
Expand Up @@ -105,7 +105,7 @@
<spotbugs.version>4.0.0-beta3</spotbugs.version>
<spotbugs.maven.version>3.1.12.2</spotbugs.maven.version>
<proton-j-version>0.31.0</proton-j-version>
<qpid-proton-j-extensions-version>1.2.0</qpid-proton-j-extensions-version>
<qpid-proton-j-extensions-version>1.2.1</qpid-proton-j-extensions-version>
<log4j-api.version>2.11.1</log4j-api.version>
<groovy-eclipse-compiler.version>3.4.0-01</groovy-eclipse-compiler.version>
<groovy-eclipse-batch.version>2.5.8-01</groovy-eclipse-batch.version>
Expand Down
4 changes: 2 additions & 2 deletions sdk/eventhubs/microsoft-azure-eventhubs-eph/pom.xml
Expand Up @@ -14,7 +14,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-eventhubs-eph</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>

<name>Microsoft Azure SDK for Event Hubs Event Processor Host(EPH)</name>
<description>EPH is built on top of the Azure Event Hubs Client and provides a number of features not present in that lower layer</description>
Expand All @@ -35,7 +35,7 @@
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-eventhubs</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
Expand Down
4 changes: 2 additions & 2 deletions sdk/eventhubs/microsoft-azure-eventhubs-extensions/pom.xml
Expand Up @@ -14,7 +14,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-eventhubs-extensions</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>

<name>Microsoft Azure SDK for Event Hubs Extensions</name>
<description>Extensions built on Microsoft Azure Event Hubs</description>
Expand All @@ -35,7 +35,7 @@
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-eventhubs</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
Expand Down
7 changes: 6 additions & 1 deletion sdk/eventhubs/microsoft-azure-eventhubs/pom.xml
Expand Up @@ -14,7 +14,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-eventhubs</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>

<name>Microsoft Azure SDK for Event Hubs</name>
<description>Libraries built on Microsoft Azure Event Hubs</description>
Expand Down Expand Up @@ -78,6 +78,11 @@
<artifactId>adal4j</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<!-- <build>-->
Expand Down
Expand Up @@ -50,6 +50,26 @@ static EventHubClient createFromConnectionStringSync(final String connectionStri
return ExceptionUtil.syncWithIOException(() -> createFromConnectionString(connectionString, retryPolicy, executor).get());
}

/**
* Synchronous version of {@link #createFromConnectionString(String, RetryPolicy, ScheduledExecutorService, ProxyConfiguration)}.
*
* @param connectionString The connection string to be used. See {@link ConnectionStringBuilder} to construct a connectionString.
* @param retryPolicy A custom {@link RetryPolicy} to be used when communicating with EventHub.
* @param executor An {@link ScheduledExecutorService} to run all tasks performed by {@link EventHubClient}.
* @param configuration The proxy configuration for this EventHubClient connection; {@code null} or
* {@link ProxyConfiguration#SYSTEM_DEFAULTS} if the system configured proxy settings should be used.
* @return EventHubClient which can be used to create Senders and Receivers to EventHub
* @throws EventHubException If Service Bus service encountered problems during connection creation.
* @throws IOException If the underlying Proton-J layer encounter network errors.
*/
static EventHubClient createFromConnectionStringSync(final String connectionString, final RetryPolicy retryPolicy,
final ScheduledExecutorService executor,
final ProxyConfiguration configuration)
throws EventHubException, IOException {
return ExceptionUtil.syncWithIOException(() -> createFromConnectionString(connectionString, retryPolicy, executor, configuration).get());
}


/**
* Factory method to create an instance of {@link EventHubClient} using the supplied connectionString.
* In a normal scenario (when re-direct is not enabled) - one EventHubClient instance maps to one Connection to the Azure ServiceBus EventHubs service.
Expand Down Expand Up @@ -81,7 +101,29 @@ static CompletableFuture<EventHubClient> createFromConnectionString(final String
static CompletableFuture<EventHubClient> createFromConnectionString(
final String connectionString, final RetryPolicy retryPolicy, final ScheduledExecutorService executor)
throws EventHubException, IOException {
return EventHubClientImpl.create(connectionString, retryPolicy, executor);
return EventHubClientImpl.create(connectionString, retryPolicy, executor, null);
}

/**
* Factory method to create an instance of {@link EventHubClient} using the supplied {@code connectionString}. One
* EventHubClient instance maps to one connection to the Event Hubs service.
*
* <p>
* The {@link EventHubClient} created from this method creates a Sender instance internally, which is used by
* the {@link #send(EventData)} methods.
* </p>
* @param connectionString The connection string to be used. See {@link ConnectionStringBuilder} to construct a connectionString.
* @param retryPolicy A custom {@link RetryPolicy} to be used when communicating with EventHub.
* @param executor An {@link ScheduledExecutorService} to run all tasks performed by {@link EventHubClient}.
* @param proxyConfiguration The proxy configuration for this EventHubClient connection; {@code null} or
* {@link ProxyConfiguration#SYSTEM_DEFAULTS} if the system configured proxy settings should be used.
* @return CompletableFuture{@literal <EventHubClient>} which can be used to create Senders and Receivers to EventHub.
* @throws IOException If the underlying Proton-J layer encounter network errors.
*/
static CompletableFuture<EventHubClient> createFromConnectionString(
final String connectionString, final RetryPolicy retryPolicy, final ScheduledExecutorService executor,
final ProxyConfiguration proxyConfiguration) throws IOException {
return EventHubClientImpl.create(connectionString, retryPolicy, executor, proxyConfiguration);
}

/**
Expand All @@ -94,7 +136,7 @@ static CompletableFuture<EventHubClient> createFromConnectionString(
* @param authCallback A callback which returns a JSON Web Token obtained from AAD.
* @param authority Address of the AAD authority to issue the token.
* @param executor An {@link ScheduledExecutorService} to run all tasks performed by {@link EventHubClient}.
* @param options Options {@link EventHubClientOptions} for creating the client. Uses all defaults if null.
* @param options Options {@link EventHubClientOptions} for creating the client. Uses all defaults if null.
* @return EventHubClient which can be used to create Senders and Receivers to EventHub
* @throws EventHubException If the EventHubs service encountered problems during connection creation.
* @throws IOException If the underlying Proton-J layer encounter network errors.
Expand All @@ -109,7 +151,7 @@ static CompletableFuture<EventHubClient> createWithAzureActiveDirectory(
ITokenProvider tokenProvider = new AzureActiveDirectoryTokenProvider(authCallback, authority, null);
return createWithTokenProvider(endpointAddress, eventHubName, tokenProvider, executor, options);
}

/**
* Factory method to create an instance of {@link EventHubClient} using the supplied namespace endpoint address, eventhub name and authentication mechanism.
* In a normal scenario (when re-direct is not enabled) - one EventHubClient instance maps to one Connection to the Azure ServiceBus EventHubs service.
Expand All @@ -119,7 +161,7 @@ static CompletableFuture<EventHubClient> createWithAzureActiveDirectory(
* @param eventHubName EventHub name
* @param tokenProvider The {@link ITokenProvider} implementation to be used to authenticate
* @param executor An {@link ScheduledExecutorService} to run all tasks performed by {@link EventHubClient}.
* @param options Options {@link EventHubClientOptions} for creating the client. Uses all defaults if null.
* @param options Options {@link EventHubClientOptions} for creating the client. Uses all defaults if null.
* @return EventHubClient which can be used to create Senders and Receivers to EventHub
* @throws EventHubException If the EventHubs service encountered problems during connection creation.
* @throws IOException If the underlying Proton-J layer encounter network errors.
Expand Down
Expand Up @@ -13,13 +13,14 @@ public class EventHubClientOptions {
private Duration operationTimeout = null;
private TransportType transportType = null;
private RetryPolicy retryPolicy = null;
private ProxyConfiguration proxyConfiguration = null;

/**
* Create with all defaults
*/
public EventHubClientOptions() {
}

/**
* Set the operation timeout.
* @param operationTimeout new operation timeout, null to unset any previous value
Expand All @@ -29,15 +30,15 @@ public EventHubClientOptions setOperationTimeout(Duration operationTimeout) {
this.operationTimeout = operationTimeout;
return this;
}

/**
* Get the operation timeout.
* @return operation timeout or null if not set
*/
public Duration getOperationTimeout() {
return this.operationTimeout;
}

/**
* Set the {@link TransportType} for the connection to the Event Hubs service
* @param transportType new transport type, null to unset any previous value
Expand All @@ -47,15 +48,15 @@ public EventHubClientOptions setTransportType(TransportType transportType) {
this.transportType = transportType;
return this;
}

/**
* Get the transport type
* @return {@link TransportType} or null if not set
*/
public TransportType getTransportType() {
return this.transportType;
}

/**
* Set the {@link RetryPolicy} for operations
* @param retryPolicy new retry policy, null to unset any previous value
Expand All @@ -65,12 +66,32 @@ public EventHubClientOptions setRetryPolicy(RetryPolicy retryPolicy) {
this.retryPolicy = retryPolicy;
return this;
}

/**
* Get the retry policy
* @return {@link RetryPolicy} or null if not set
*/
public RetryPolicy getRetryPolicy() {
return this.retryPolicy;
}

/**
* Sets the proxy configuration for the client options.
*
* @param proxyConfiguration The proxy configuration to set on the options.
* @return The updated options object.
*/
public EventHubClientOptions setProxyConfiguration(ProxyConfiguration proxyConfiguration) {
this.proxyConfiguration = proxyConfiguration;
return this;
}

/**
* Gets the proxy configuration for this set of options.
*
* @return Gets the proxy configuration.
*/
public ProxyConfiguration getProxyConfiguration() {
return proxyConfiguration;
}
}
@@ -0,0 +1,140 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.azure.eventhubs;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.PasswordAuthentication;
import java.util.Arrays;
import java.util.Objects;

public class ProxyConfiguration implements AutoCloseable {
private static final Logger LOGGER = LoggerFactory.getLogger(ProxyConfiguration.class);

private final java.net.Proxy proxyAddress;
private final ProxyAuthenticationType authentication;
private final PasswordAuthentication credentials;

/**
* Gets the system defaults for proxy configuration and authentication.
*/
public static final ProxyConfiguration SYSTEM_DEFAULTS = new ProxyConfiguration();

/**
* Creates a proxy configuration that uses the system-wide proxy configuration and authenticator.
*/
private ProxyConfiguration() {
this.authentication = null;
this.credentials = null;
this.proxyAddress = null;
}

/**
* Creates a proxy configuration that uses the {@code proxyAddress} and authenticates with provided
* {@code username}, {@code password} and {@code authentication}.
*
* @param authentication Authentication method to preemptively use with proxy.
* @param proxyAddress Proxy to use. If {@code null} is passed in, then the system configured {@link java.net.Proxy}
* is used.
* @param username Optional. Username used to authenticate with proxy. If not specified, the system-wide
* {@link java.net.Authenticator} is used to fetch credentials.
* @param password Optional. Password used to authenticate with proxy.
*
* @throws NullPointerException if {@code authentication} is {@code null}.
* @throws IllegalArgumentException if {@code authentication} is {@link ProxyAuthenticationType#BASIC} or
* {@link ProxyAuthenticationType#DIGEST} and {@code username} or {@code password} are {@code null}.
*/
public ProxyConfiguration(ProxyAuthenticationType authentication, java.net.Proxy proxyAddress, String username, String password) {
Objects.requireNonNull(authentication);

this.proxyAddress = proxyAddress;
this.authentication = authentication;

if (username != null && password != null) {
this.credentials = new PasswordAuthentication(username, password.toCharArray());
} else {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("username or password is null. Using system-wide authentication.");
}

this.credentials = null;
}
}

/**
* Gets the proxy address.
*
* @return The proxy address. Returns {@code null} if user creates proxy credentials with
* {@link ProxyConfiguration#SYSTEM_DEFAULTS}.
*/
public java.net.Proxy proxyAddress() {
return proxyAddress;
}

/**
* Gets credentials to authenticate against proxy with.
*
* @return The credentials to authenticate against proxy with. Returns {@code null} if no credentials were set. This
* occurs when user uses {@link ProxyConfiguration#SYSTEM_DEFAULTS}.
*/
public PasswordAuthentication credentials() {
return credentials;
}

/**
* Gets the proxy authentication type to use.
*
* @return The proxy authentication type to use. returns {@code null} if no authentication type was set. This occurs
* when user uses {@link ProxyConfiguration#SYSTEM_DEFAULTS}.
*/
public ProxyAuthenticationType authentication() {
return authentication;
}

/**
* Gets whether the user has defined credentials.
*
* @return true if the user has defined the credentials to use, false otherwise.
*/
public boolean hasUserDefinedCredentials() {
return credentials != null;
}

/**
* Gets whether the proxy address has been configured. Used to determine whether to use system-defined or
* user-defined proxy.
*
* @return true if the proxy url has been set, and false otherwise.
*/
public boolean isProxyAddressConfigured() {
return proxyAddress != null && proxyAddress.address() != null;
}

@Override
public void close() {
// It is up to us to clear the password field when we are done using it.
if (credentials != null) {
Arrays.fill(credentials.getPassword(), '\0');
}
}

/**
* Supported methods of proxy authentication.
*/
public enum ProxyAuthenticationType {
/**
* Proxy requires no authentication. Service calls will fail if proxy demands authentication.
*/
NONE,
/**
* Authenticates against proxy with basic authentication scheme.
*/
BASIC,
/**
* Authenticates against proxy with digest access authentication.
*/
DIGEST,
}
}