Add proxy username and password settings for Azure repository (#2098)

Added username/password proxy settings for Azure repository.
Security settings:
- azure.client.*.proxy.username - Proxy user name
- azure.client.*.proxy.password - Proxy user password

Signed-off-by: Andrey Pleskach <ples@aiven.io>
This commit is contained in:
Andrey Pleskach 2022-02-15 19:40:47 +01:00 committed by GitHub
parent 6b6f03368f
commit 62361ceafc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 239 additions and 87 deletions

View File

@ -94,13 +94,15 @@ public class AzureRepositoryPlugin extends Plugin implements RepositoryPlugin, R
AzureStorageSettings.ENDPOINT_SUFFIX_SETTING, AzureStorageSettings.ENDPOINT_SUFFIX_SETTING,
AzureStorageSettings.TIMEOUT_SETTING, AzureStorageSettings.TIMEOUT_SETTING,
AzureStorageSettings.MAX_RETRIES_SETTING, AzureStorageSettings.MAX_RETRIES_SETTING,
AzureStorageSettings.PROXY_TYPE_SETTING,
AzureStorageSettings.PROXY_HOST_SETTING,
AzureStorageSettings.PROXY_PORT_SETTING,
AzureStorageSettings.CONNECT_TIMEOUT_SETTING, AzureStorageSettings.CONNECT_TIMEOUT_SETTING,
AzureStorageSettings.WRITE_TIMEOUT_SETTING, AzureStorageSettings.WRITE_TIMEOUT_SETTING,
AzureStorageSettings.READ_TIMEOUT_SETTING, AzureStorageSettings.READ_TIMEOUT_SETTING,
AzureStorageSettings.RESPONSE_TIMEOUT_SETTING AzureStorageSettings.RESPONSE_TIMEOUT_SETTING,
AzureStorageSettings.PROXY_TYPE_SETTING,
AzureStorageSettings.PROXY_HOST_SETTING,
AzureStorageSettings.PROXY_PORT_SETTING,
AzureStorageSettings.PROXY_USERNAME_SETTING,
AzureStorageSettings.PROXY_PASSWORD_SETTING
); );
} }

View File

@ -43,7 +43,6 @@ import com.azure.core.http.HttpPipelinePosition;
import com.azure.core.http.HttpRequest; import com.azure.core.http.HttpRequest;
import com.azure.core.http.HttpResponse; import com.azure.core.http.HttpResponse;
import com.azure.core.http.ProxyOptions; import com.azure.core.http.ProxyOptions;
import com.azure.core.http.ProxyOptions.Type;
import com.azure.core.http.netty.NettyAsyncHttpClientBuilder; import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.http.policy.HttpPipelinePolicy;
import com.azure.core.util.Configuration; import com.azure.core.util.Configuration;
@ -66,12 +65,11 @@ import org.opensearch.common.unit.ByteSizeUnit;
import org.opensearch.common.unit.ByteSizeValue; import org.opensearch.common.unit.ByteSizeValue;
import org.opensearch.common.unit.TimeValue; import org.opensearch.common.unit.TimeValue;
import java.net.InetSocketAddress; import java.net.Authenticator;
import java.net.Proxy; import java.net.PasswordAuthentication;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -169,15 +167,20 @@ public class AzureStorageService implements AutoCloseable {
final NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup(new NioThreadFactory()); final NioEventLoopGroup eventLoopGroup = new NioEventLoopGroup(new NioThreadFactory());
final NettyAsyncHttpClientBuilder clientBuilder = new NettyAsyncHttpClientBuilder().eventLoopGroup(eventLoopGroup); final NettyAsyncHttpClientBuilder clientBuilder = new NettyAsyncHttpClientBuilder().eventLoopGroup(eventLoopGroup);
final Proxy proxy = azureStorageSettings.getProxy(); SocketAccess.doPrivilegedVoidException(() -> {
if (proxy != null) { final ProxySettings proxySettings = azureStorageSettings.getProxySettings();
final Type type = Arrays.stream(Type.values()) if (proxySettings != ProxySettings.NO_PROXY_SETTINGS) {
.filter(t -> t.toProxyType().equals(proxy.type())) if (proxySettings.isAuthenticated()) {
.findFirst() Authenticator.setDefault(new Authenticator() {
.orElseThrow(() -> new IllegalArgumentException("Unsupported proxy type: " + proxy.type())); @Override
protected PasswordAuthentication getPasswordAuthentication() {
clientBuilder.proxy(new ProxyOptions(type, (InetSocketAddress) proxy.address())); return new PasswordAuthentication(proxySettings.getUsername(), proxySettings.getPassword().toCharArray());
} }
});
}
clientBuilder.proxy(new ProxyOptions(proxySettings.getType().toProxyType(), proxySettings.getAddress()));
}
});
final TimeValue connectTimeout = azureStorageSettings.getConnectTimeout(); final TimeValue connectTimeout = azureStorageSettings.getConnectTimeout();
if (connectTimeout != null) { if (connectTimeout != null) {

View File

@ -44,8 +44,6 @@ import org.opensearch.common.settings.Settings;
import org.opensearch.common.settings.SettingsException; import org.opensearch.common.settings.SettingsException;
import org.opensearch.common.unit.TimeValue; import org.opensearch.common.unit.TimeValue;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -143,10 +141,10 @@ final class AzureStorageSettings {
); );
/** The type of the proxy to connect to azure through. Can be direct (no proxy, default), http or socks */ /** The type of the proxy to connect to azure through. Can be direct (no proxy, default), http or socks */
public static final AffixSetting<Proxy.Type> PROXY_TYPE_SETTING = Setting.affixKeySetting( public static final AffixSetting<ProxySettings.ProxyType> PROXY_TYPE_SETTING = Setting.affixKeySetting(
AZURE_CLIENT_PREFIX_KEY, AZURE_CLIENT_PREFIX_KEY,
"proxy.type", "proxy.type",
(key) -> new Setting<>(key, "direct", s -> Proxy.Type.valueOf(s.toUpperCase(Locale.ROOT)), Property.NodeScope), (key) -> new Setting<>(key, "direct", s -> ProxySettings.ProxyType.valueOf(s.toUpperCase(Locale.ROOT)), Property.NodeScope),
() -> ACCOUNT_SETTING, () -> ACCOUNT_SETTING,
() -> KEY_SETTING () -> KEY_SETTING
); );
@ -162,27 +160,50 @@ final class AzureStorageSettings {
); );
/** The port of a proxy to connect to azure through. */ /** The port of a proxy to connect to azure through. */
public static final Setting<Integer> PROXY_PORT_SETTING = Setting.affixKeySetting( public static final AffixSetting<Integer> PROXY_PORT_SETTING = Setting.affixKeySetting(
AZURE_CLIENT_PREFIX_KEY, AZURE_CLIENT_PREFIX_KEY,
"proxy.port", "proxy.port",
(key) -> Setting.intSetting(key, 0, 0, 65535, Setting.Property.NodeScope), (key) -> Setting.intSetting(key, 0, 0, 65535, Setting.Property.NodeScope),
() -> ACCOUNT_SETTING,
() -> KEY_SETTING, () -> KEY_SETTING,
() -> ACCOUNT_SETTING,
() -> PROXY_TYPE_SETTING, () -> PROXY_TYPE_SETTING,
() -> PROXY_HOST_SETTING () -> PROXY_HOST_SETTING
); );
/** The username of a proxy to connect */
static final AffixSetting<SecureString> PROXY_USERNAME_SETTING = Setting.affixKeySetting(
AZURE_CLIENT_PREFIX_KEY,
"proxy.username",
key -> SecureSetting.secureString(key, null),
() -> KEY_SETTING,
() -> ACCOUNT_SETTING,
() -> PROXY_TYPE_SETTING,
() -> PROXY_HOST_SETTING
);
/** The password of a proxy to connect */
static final AffixSetting<SecureString> PROXY_PASSWORD_SETTING = Setting.affixKeySetting(
AZURE_CLIENT_PREFIX_KEY,
"proxy.password",
key -> SecureSetting.secureString(key, null),
() -> KEY_SETTING,
() -> ACCOUNT_SETTING,
() -> PROXY_TYPE_SETTING,
() -> PROXY_HOST_SETTING,
() -> PROXY_USERNAME_SETTING
);
private final String account; private final String account;
private final String connectString; private final String connectString;
private final String endpointSuffix; private final String endpointSuffix;
private final TimeValue timeout; private final TimeValue timeout;
private final int maxRetries; private final int maxRetries;
private final Proxy proxy;
private final LocationMode locationMode; private final LocationMode locationMode;
private final TimeValue connectTimeout; private final TimeValue connectTimeout;
private final TimeValue writeTimeout; private final TimeValue writeTimeout;
private final TimeValue readTimeout; private final TimeValue readTimeout;
private final TimeValue responseTimeout; private final TimeValue responseTimeout;
private final ProxySettings proxySettings;
// copy-constructor // copy-constructor
private AzureStorageSettings( private AzureStorageSettings(
@ -191,24 +212,24 @@ final class AzureStorageSettings {
String endpointSuffix, String endpointSuffix,
TimeValue timeout, TimeValue timeout,
int maxRetries, int maxRetries,
Proxy proxy,
LocationMode locationMode, LocationMode locationMode,
TimeValue connectTimeout, TimeValue connectTimeout,
TimeValue writeTimeout, TimeValue writeTimeout,
TimeValue readTimeout, TimeValue readTimeout,
TimeValue responseTimeout TimeValue responseTimeout,
ProxySettings proxySettings
) { ) {
this.account = account; this.account = account;
this.connectString = connectString; this.connectString = connectString;
this.endpointSuffix = endpointSuffix; this.endpointSuffix = endpointSuffix;
this.timeout = timeout; this.timeout = timeout;
this.maxRetries = maxRetries; this.maxRetries = maxRetries;
this.proxy = proxy;
this.locationMode = locationMode; this.locationMode = locationMode;
this.connectTimeout = connectTimeout; this.connectTimeout = connectTimeout;
this.writeTimeout = writeTimeout; this.writeTimeout = writeTimeout;
this.readTimeout = readTimeout; this.readTimeout = readTimeout;
this.responseTimeout = responseTimeout; this.responseTimeout = responseTimeout;
this.proxySettings = proxySettings;
} }
private AzureStorageSettings( private AzureStorageSettings(
@ -218,42 +239,23 @@ final class AzureStorageSettings {
String endpointSuffix, String endpointSuffix,
TimeValue timeout, TimeValue timeout,
int maxRetries, int maxRetries,
Proxy.Type proxyType,
String proxyHost,
Integer proxyPort,
TimeValue connectTimeout, TimeValue connectTimeout,
TimeValue writeTimeout, TimeValue writeTimeout,
TimeValue readTimeout, TimeValue readTimeout,
TimeValue responseTimeout TimeValue responseTimeout,
ProxySettings proxySettings
) { ) {
this.account = account; this.account = account;
this.connectString = buildConnectString(account, key, sasToken, endpointSuffix); this.connectString = buildConnectString(account, key, sasToken, endpointSuffix);
this.endpointSuffix = endpointSuffix; this.endpointSuffix = endpointSuffix;
this.timeout = timeout; this.timeout = timeout;
this.maxRetries = maxRetries; this.maxRetries = maxRetries;
// Register the proxy if we have any
// Validate proxy settings
if (proxyType.equals(Proxy.Type.DIRECT) && ((proxyPort != 0) || Strings.hasText(proxyHost))) {
throw new SettingsException("Azure Proxy port or host have been set but proxy type is not defined.");
}
if ((proxyType.equals(Proxy.Type.DIRECT) == false) && ((proxyPort == 0) || Strings.isEmpty(proxyHost))) {
throw new SettingsException("Azure Proxy type has been set but proxy host or port is not defined.");
}
if (proxyType.equals(Proxy.Type.DIRECT)) {
proxy = null;
} else {
try {
proxy = new Proxy(proxyType, new InetSocketAddress(InetAddress.getByName(proxyHost), proxyPort));
} catch (final UnknownHostException e) {
throw new SettingsException("Azure proxy host is unknown.", e);
}
}
this.locationMode = LocationMode.PRIMARY_ONLY; this.locationMode = LocationMode.PRIMARY_ONLY;
this.connectTimeout = connectTimeout; this.connectTimeout = connectTimeout;
this.writeTimeout = writeTimeout; this.writeTimeout = writeTimeout;
this.readTimeout = readTimeout; this.readTimeout = readTimeout;
this.responseTimeout = responseTimeout; this.responseTimeout = responseTimeout;
this.proxySettings = proxySettings;
} }
public String getEndpointSuffix() { public String getEndpointSuffix() {
@ -268,8 +270,8 @@ final class AzureStorageSettings {
return maxRetries; return maxRetries;
} }
public Proxy getProxy() { public ProxySettings getProxySettings() {
return proxy; return proxySettings;
} }
public String getConnectString() { public String getConnectString() {
@ -325,7 +327,7 @@ final class AzureStorageSettings {
sb.append(", timeout=").append(timeout); sb.append(", timeout=").append(timeout);
sb.append(", endpointSuffix='").append(endpointSuffix).append('\''); sb.append(", endpointSuffix='").append(endpointSuffix).append('\'');
sb.append(", maxRetries=").append(maxRetries); sb.append(", maxRetries=").append(maxRetries);
sb.append(", proxy=").append(proxy); sb.append(", proxySettings=").append(proxySettings != ProxySettings.NO_PROXY_SETTINGS ? "PROXY_SET" : "PROXY_NOT_SET");
sb.append(", locationMode='").append(locationMode).append('\''); sb.append(", locationMode='").append(locationMode).append('\'');
sb.append(", connectTimeout='").append(connectTimeout).append('\''); sb.append(", connectTimeout='").append(connectTimeout).append('\'');
sb.append(", writeTimeout='").append(writeTimeout).append('\''); sb.append(", writeTimeout='").append(writeTimeout).append('\'');
@ -371,17 +373,42 @@ final class AzureStorageSettings {
getValue(settings, clientName, ENDPOINT_SUFFIX_SETTING), getValue(settings, clientName, ENDPOINT_SUFFIX_SETTING),
getValue(settings, clientName, TIMEOUT_SETTING), getValue(settings, clientName, TIMEOUT_SETTING),
getValue(settings, clientName, MAX_RETRIES_SETTING), getValue(settings, clientName, MAX_RETRIES_SETTING),
getValue(settings, clientName, PROXY_TYPE_SETTING),
getValue(settings, clientName, PROXY_HOST_SETTING),
getValue(settings, clientName, PROXY_PORT_SETTING),
getValue(settings, clientName, CONNECT_TIMEOUT_SETTING), getValue(settings, clientName, CONNECT_TIMEOUT_SETTING),
getValue(settings, clientName, WRITE_TIMEOUT_SETTING), getValue(settings, clientName, WRITE_TIMEOUT_SETTING),
getValue(settings, clientName, READ_TIMEOUT_SETTING), getValue(settings, clientName, READ_TIMEOUT_SETTING),
getValue(settings, clientName, RESPONSE_TIMEOUT_SETTING) getValue(settings, clientName, RESPONSE_TIMEOUT_SETTING),
validateAndCreateProxySettings(settings, clientName)
); );
} }
} }
static ProxySettings validateAndCreateProxySettings(final Settings settings, final String clientName) {
final ProxySettings.ProxyType proxyType = getConfigValue(settings, clientName, PROXY_TYPE_SETTING);
final String proxyHost = getConfigValue(settings, clientName, PROXY_HOST_SETTING);
final int proxyPort = getConfigValue(settings, clientName, PROXY_PORT_SETTING);
final SecureString proxyUserName = getConfigValue(settings, clientName, PROXY_USERNAME_SETTING);
final SecureString proxyPassword = getConfigValue(settings, clientName, PROXY_PASSWORD_SETTING);
// Validate proxy settings
if (proxyType == ProxySettings.ProxyType.DIRECT
&& (proxyPort != 0 || Strings.hasText(proxyHost) || Strings.hasText(proxyUserName) || Strings.hasText(proxyPassword))) {
throw new SettingsException("Azure proxy port or host or username or password have been set but proxy type is not defined.");
}
if (proxyType != ProxySettings.ProxyType.DIRECT && (proxyPort == 0 || Strings.isEmpty(proxyHost))) {
throw new SettingsException("Azure proxy type has been set but proxy host or port is not defined.");
}
if (proxyType == ProxySettings.ProxyType.DIRECT) {
return ProxySettings.NO_PROXY_SETTINGS;
}
try {
final InetAddress proxyHostAddress = InetAddress.getByName(proxyHost);
return new ProxySettings(proxyType, proxyHostAddress, proxyPort, proxyUserName.toString(), proxyPassword.toString());
} catch (final UnknownHostException e) {
throw new SettingsException("Azure proxy host is unknown.", e);
}
}
private static <T> T getConfigValue(Settings settings, String clientName, Setting.AffixSetting<T> clientSetting) { private static <T> T getConfigValue(Settings settings, String clientName, Setting.AffixSetting<T> clientSetting) {
final Setting<T> concreteSetting = clientSetting.getConcreteSettingForNamespace(clientName); final Setting<T> concreteSetting = clientSetting.getConcreteSettingForNamespace(clientName);
return concreteSetting.get(settings); return concreteSetting.get(settings);
@ -407,12 +434,12 @@ final class AzureStorageSettings {
entry.getValue().endpointSuffix, entry.getValue().endpointSuffix,
entry.getValue().timeout, entry.getValue().timeout,
entry.getValue().maxRetries, entry.getValue().maxRetries,
entry.getValue().proxy,
locationMode, locationMode,
entry.getValue().connectTimeout, entry.getValue().connectTimeout,
entry.getValue().writeTimeout, entry.getValue().writeTimeout,
entry.getValue().readTimeout, entry.getValue().readTimeout,
entry.getValue().responseTimeout entry.getValue().responseTimeout,
entry.getValue().getProxySettings()
) )
); );
} }

View File

@ -0,0 +1,110 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
package org.opensearch.repositories.azure;
import com.azure.core.http.ProxyOptions;
import org.opensearch.common.Strings;
import org.opensearch.common.settings.SettingsException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Objects;
public class ProxySettings {
public static final ProxySettings NO_PROXY_SETTINGS = new ProxySettings(ProxyType.DIRECT, null, -1, null, null);
private final ProxyType type;
private final InetAddress host;
private final String username;
private final String password;
private final int port;
public static enum ProxyType {
HTTP(ProxyOptions.Type.HTTP.name()),
/**
* Please use SOCKS4 instead
*/
@Deprecated
SOCKS(ProxyOptions.Type.SOCKS4.name()),
SOCKS4(ProxyOptions.Type.SOCKS4.name()),
SOCKS5(ProxyOptions.Type.SOCKS5.name()),
DIRECT("DIRECT");
private final String name;
private ProxyType(String name) {
this.name = name;
}
public ProxyOptions.Type toProxyType() {
if (this == DIRECT) {
// We check it in settings,
// the probability that it could be thrown is small, but how knows
throw new SettingsException("Couldn't convert to Azure proxy type");
}
return ProxyOptions.Type.valueOf(name());
}
}
public ProxySettings(final ProxyType type, final InetAddress host, final int port, final String username, final String password) {
this.type = type;
this.host = host;
this.port = port;
this.username = username;
this.password = password;
}
public ProxyType getType() {
return this.type;
}
public InetSocketAddress getAddress() {
return new InetSocketAddress(host, port);
}
public String getUsername() {
return this.username;
}
public String getPassword() {
return this.password;
}
public boolean isAuthenticated() {
return Strings.isNullOrEmpty(username) == false && Strings.isNullOrEmpty(password) == false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final ProxySettings that = (ProxySettings) o;
return port == that.port
&& type == that.type
&& Objects.equals(host, that.host)
&& Objects.equals(username, that.username)
&& Objects.equals(password, that.password);
}
@Override
public int hashCode() {
return Objects.hash(type, host, username, password, port);
}
}

View File

@ -38,4 +38,7 @@ grant {
permission java.lang.RuntimePermission "accessDeclaredMembers"; permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.lang.RuntimePermission "setContextClassLoader"; permission java.lang.RuntimePermission "setContextClassLoader";
// azure client set Authenticator for proxy username/password
permission java.net.NetPermission "setDefaultAuthenticator";
}; };

View File

@ -32,6 +32,7 @@
package org.opensearch.repositories.azure; package org.opensearch.repositories.azure;
import org.opensearch.common.Strings;
import reactor.core.scheduler.Schedulers; import reactor.core.scheduler.Schedulers;
import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.http.policy.HttpPipelinePolicy;
@ -50,7 +51,6 @@ import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@ -299,9 +299,9 @@ public class AzureStorageServiceTests extends OpenSearchTestCase {
public void testNoProxy() { public void testNoProxy() {
final Settings settings = Settings.builder().setSecureSettings(buildSecureSettings()).build(); final Settings settings = Settings.builder().setSecureSettings(buildSecureSettings()).build();
final AzureStorageService mock = storageServiceWithSettingsValidation(settings); final AzureStorageService mock = storageServiceWithSettingsValidation(settings);
assertThat(mock.storageSettings.get("azure1").getProxy(), nullValue()); assertEquals(mock.storageSettings.get("azure1").getProxySettings(), ProxySettings.NO_PROXY_SETTINGS);
assertThat(mock.storageSettings.get("azure2").getProxy(), nullValue()); assertEquals(mock.storageSettings.get("azure2").getProxySettings(), ProxySettings.NO_PROXY_SETTINGS);
assertThat(mock.storageSettings.get("azure3").getProxy(), nullValue()); assertEquals(mock.storageSettings.get("azure3").getProxySettings(), ProxySettings.NO_PROXY_SETTINGS);
} }
public void testProxyHttp() throws UnknownHostException { public void testProxyHttp() throws UnknownHostException {
@ -312,13 +312,13 @@ public class AzureStorageServiceTests extends OpenSearchTestCase {
.put("azure.client.azure1.proxy.type", "http") .put("azure.client.azure1.proxy.type", "http")
.build(); .build();
final AzureStorageService mock = storageServiceWithSettingsValidation(settings); final AzureStorageService mock = storageServiceWithSettingsValidation(settings);
final Proxy azure1Proxy = mock.storageSettings.get("azure1").getProxy(); final ProxySettings azure1Proxy = mock.storageSettings.get("azure1").getProxySettings();
assertThat(azure1Proxy, notNullValue()); assertThat(azure1Proxy, notNullValue());
assertThat(azure1Proxy.type(), is(Proxy.Type.HTTP)); assertThat(azure1Proxy.getType(), is(ProxySettings.ProxyType.HTTP));
assertThat(azure1Proxy.address(), is(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8080))); assertThat(azure1Proxy.getAddress(), is(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8080)));
assertThat(mock.storageSettings.get("azure2").getProxy(), nullValue()); assertEquals(ProxySettings.NO_PROXY_SETTINGS, mock.storageSettings.get("azure2").getProxySettings());
assertThat(mock.storageSettings.get("azure3").getProxy(), nullValue()); assertEquals(ProxySettings.NO_PROXY_SETTINGS, mock.storageSettings.get("azure3").getProxySettings());
} }
public void testMultipleProxies() throws UnknownHostException { public void testMultipleProxies() throws UnknownHostException {
@ -332,52 +332,59 @@ public class AzureStorageServiceTests extends OpenSearchTestCase {
.put("azure.client.azure2.proxy.type", "http") .put("azure.client.azure2.proxy.type", "http")
.build(); .build();
final AzureStorageService mock = storageServiceWithSettingsValidation(settings); final AzureStorageService mock = storageServiceWithSettingsValidation(settings);
final Proxy azure1Proxy = mock.storageSettings.get("azure1").getProxy(); final ProxySettings azure1Proxy = mock.storageSettings.get("azure1").getProxySettings();
assertThat(azure1Proxy, notNullValue()); assertThat(azure1Proxy, notNullValue());
assertThat(azure1Proxy.type(), is(Proxy.Type.HTTP)); assertThat(azure1Proxy.getType(), is(ProxySettings.ProxyType.HTTP));
assertThat(azure1Proxy.address(), is(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8080))); assertThat(azure1Proxy.getAddress(), is(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8080)));
final Proxy azure2Proxy = mock.storageSettings.get("azure2").getProxy(); final ProxySettings azure2Proxy = mock.storageSettings.get("azure2").getProxySettings();
assertThat(azure2Proxy, notNullValue()); assertThat(azure2Proxy, notNullValue());
assertThat(azure2Proxy.type(), is(Proxy.Type.HTTP)); assertThat(azure2Proxy.getType(), is(ProxySettings.ProxyType.HTTP));
assertThat(azure2Proxy.address(), is(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8081))); assertThat(azure2Proxy.getAddress(), is(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8081)));
assertThat(mock.storageSettings.get("azure3").getProxy(), nullValue()); assertTrue(Strings.isNullOrEmpty(azure2Proxy.getUsername()));
assertTrue(Strings.isNullOrEmpty(azure2Proxy.getPassword()));
assertEquals(mock.storageSettings.get("azure3").getProxySettings(), ProxySettings.NO_PROXY_SETTINGS);
} }
public void testProxySocks() throws UnknownHostException { public void testProxySocks() throws UnknownHostException {
final MockSecureSettings secureSettings = buildSecureSettings();
secureSettings.setString("azure.client.azure1.proxy.username", "user");
secureSettings.setString("azure.client.azure1.proxy.password", "pwd");
final Settings settings = Settings.builder() final Settings settings = Settings.builder()
.setSecureSettings(buildSecureSettings())
.put("azure.client.azure1.proxy.host", "127.0.0.1") .put("azure.client.azure1.proxy.host", "127.0.0.1")
.put("azure.client.azure1.proxy.port", 8080) .put("azure.client.azure1.proxy.port", 8080)
.put("azure.client.azure1.proxy.type", "socks") .put("azure.client.azure1.proxy.type", "socks5")
.setSecureSettings(secureSettings)
.build(); .build();
final AzureStorageService mock = storageServiceWithSettingsValidation(settings); final AzureStorageService mock = storageServiceWithSettingsValidation(settings);
final Proxy azure1Proxy = mock.storageSettings.get("azure1").getProxy(); final ProxySettings azure1Proxy = mock.storageSettings.get("azure1").getProxySettings();
assertThat(azure1Proxy, notNullValue()); assertThat(azure1Proxy, notNullValue());
assertThat(azure1Proxy.type(), is(Proxy.Type.SOCKS)); assertThat(azure1Proxy.getType(), is(ProxySettings.ProxyType.SOCKS5));
assertThat(azure1Proxy.address(), is(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8080))); assertThat(azure1Proxy.getAddress(), is(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 8080)));
assertThat(mock.storageSettings.get("azure2").getProxy(), nullValue()); assertEquals("user", azure1Proxy.getUsername());
assertThat(mock.storageSettings.get("azure3").getProxy(), nullValue()); assertEquals("pwd", azure1Proxy.getPassword());
assertEquals(ProxySettings.NO_PROXY_SETTINGS, mock.storageSettings.get("azure2").getProxySettings());
assertEquals(ProxySettings.NO_PROXY_SETTINGS, mock.storageSettings.get("azure3").getProxySettings());
} }
public void testProxyNoHost() { public void testProxyNoHost() {
final Settings settings = Settings.builder() final Settings settings = Settings.builder()
.setSecureSettings(buildSecureSettings()) .setSecureSettings(buildSecureSettings())
.put("azure.client.azure1.proxy.port", 8080) .put("azure.client.azure1.proxy.port", 8080)
.put("azure.client.azure1.proxy.type", randomFrom("socks", "http")) .put("azure.client.azure1.proxy.type", randomFrom("socks", "socks4", "socks5", "http"))
.build(); .build();
final SettingsException e = expectThrows(SettingsException.class, () -> storageServiceWithSettingsValidation(settings)); final SettingsException e = expectThrows(SettingsException.class, () -> storageServiceWithSettingsValidation(settings));
assertEquals("Azure Proxy type has been set but proxy host or port is not defined.", e.getMessage()); assertEquals("Azure proxy type has been set but proxy host or port is not defined.", e.getMessage());
} }
public void testProxyNoPort() { public void testProxyNoPort() {
final Settings settings = Settings.builder() final Settings settings = Settings.builder()
.setSecureSettings(buildSecureSettings()) .setSecureSettings(buildSecureSettings())
.put("azure.client.azure1.proxy.host", "127.0.0.1") .put("azure.client.azure1.proxy.host", "127.0.0.1")
.put("azure.client.azure1.proxy.type", randomFrom("socks", "http")) .put("azure.client.azure1.proxy.type", randomFrom("socks", "socks4", "socks5", "http"))
.build(); .build();
final SettingsException e = expectThrows(SettingsException.class, () -> storageServiceWithSettingsValidation(settings)); final SettingsException e = expectThrows(SettingsException.class, () -> storageServiceWithSettingsValidation(settings));
assertEquals("Azure Proxy type has been set but proxy host or port is not defined.", e.getMessage()); assertEquals("Azure proxy type has been set but proxy host or port is not defined.", e.getMessage());
} }
public void testProxyNoType() { public void testProxyNoType() {
@ -388,13 +395,13 @@ public class AzureStorageServiceTests extends OpenSearchTestCase {
.build(); .build();
final SettingsException e = expectThrows(SettingsException.class, () -> storageServiceWithSettingsValidation(settings)); final SettingsException e = expectThrows(SettingsException.class, () -> storageServiceWithSettingsValidation(settings));
assertEquals("Azure Proxy port or host have been set but proxy type is not defined.", e.getMessage()); assertEquals("Azure proxy port or host or username or password have been set but proxy type is not defined.", e.getMessage());
} }
public void testProxyWrongHost() { public void testProxyWrongHost() {
final Settings settings = Settings.builder() final Settings settings = Settings.builder()
.setSecureSettings(buildSecureSettings()) .setSecureSettings(buildSecureSettings())
.put("azure.client.azure1.proxy.type", randomFrom("socks", "http")) .put("azure.client.azure1.proxy.type", randomFrom("socks", "socks4", "socks5", "http"))
.put("azure.client.azure1.proxy.host", "thisisnotavalidhostorwehavebeensuperunlucky") .put("azure.client.azure1.proxy.host", "thisisnotavalidhostorwehavebeensuperunlucky")
.put("azure.client.azure1.proxy.port", 8080) .put("azure.client.azure1.proxy.port", 8080)
.build(); .build();