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

refactorInsecureConnectionConfig #42972

Merged
merged 4 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
"ProfileFlag": "-Pemulator-vnext",
"DESIRED_CONSISTENCIES": "[\"Session\"]",
"JavaTestVersion": "1.8",
"AdditionalArgs": "-DCOSMOS.AZURE_COSMOS_DISABLE_NON_STREAMING_ORDER_BY=true -DCOSMOS.INSECURE_EMULATOR_CONNECTION_ALLOWED=true"
"AdditionalArgs": "-DCOSMOS.AZURE_COSMOS_DISABLE_NON_STREAMING_ORDER_BY=true"
},
"Emulator VNext Integration Tests On Insecure connection - Java 17": {
"ProfileFlag": "-Pemulator-vnext",
"DESIRED_CONSISTENCIES": "[\"Session\"]",
"JavaTestVersion": "1.17",
"AdditionalArgs": "-DCOSMOS.AZURE_COSMOS_DISABLE_NON_STREAMING_ORDER_BY=true -DCOSMOS.INSECURE_EMULATOR_CONNECTION_ALLOWED=true"
"AdditionalArgs": "-DCOSMOS.AZURE_COSMOS_DISABLE_NON_STREAMING_ORDER_BY=true"
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions eng/pipelines/templates/stages/cosmos-sdk-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ extends:
SECONDARY_ACCOUNT_KEY: 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='
TimeoutInMinutes: 90
TestGoals: 'clean verify'
TestOptions: '$(ProfileFlag) $(AdditionalArgs) -DACCOUNT_HOST=http://localhost:8081/'
TestOptions: '$(ProfileFlag) $(AdditionalArgs) -DACCOUNT_HOST=http://localhost:8081/ -DCOSMOS.HTTP_CONNECTION_WITHOUT_TLS_ALLOWED=true'
PreSteps:
- template: /eng/pipelines/templates/stages/cosmos-vnext-emulator-http.yml
- stage: TestVNextEmulatorHttps
Expand Down Expand Up @@ -188,7 +188,7 @@ extends:
SECONDARY_ACCOUNT_KEY: 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=='
TimeoutInMinutes: 90
TestGoals: 'clean verify'
TestOptions: '$(ProfileFlag) $(AdditionalArgs) -DACCOUNT_HOST=https://localhost:8081/'
TestOptions: '$(ProfileFlag) $(AdditionalArgs) -DACCOUNT_HOST=https://localhost:8081/ -DCOSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED=true'
PreSteps:
- template: /eng/pipelines/templates/stages/cosmos-vnext-emulator-https.yml

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ steps:
inputs:
command: 'Run a Docker command'
action: 'Run a Docker command'
customCommand: 'run --detach --publish 8081:8081 --publish 1234:1234 -e enable-explorer=false -e GATEWAY_TLS_ENABLED=false mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview'
customCommand: 'run --detach --publish 8081:8081 --publish 1234:1234 -e ENABLE_EXPLORER=false mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview'
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.cosmos;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class ClientBuilderConnectionPolicyTests {
@DataProvider(name = "endpointArgProvider")
public static Object[][] endpointArgProvider() {
return new Object[][]{
{ "https://localhost", true },
{ "https://Localhost", true },
{ "http://Localhost", true },
{ "https://127.0.0.1", true },
{ "https://[::1]", true },
{ "https://[0:0:0:0:0:0:0:1]", true },
{ "https://random", false}
};
}

@Test(groups = "emulator", dataProvider = "endpointArgProvider")
public void clientWithServerCertValidationDisabled(String endPoint, boolean isEmulatorHost) {
System.setProperty("COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED", "true");

try {
CosmosClientBuilder clientBuilder = new CosmosClientBuilder().endpoint(endPoint).key("key");
clientBuilder.validateConfig();
clientBuilder.buildConnectionPolicy();
assertThat(clientBuilder.getConnectionPolicy().isServerCertValidationDisabled()).isEqualTo(isEmulatorHost);
} finally {
System.clearProperty("COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import com.azure.cosmos.implementation.clienttelemetry.MetricCategory;
import com.azure.cosmos.implementation.clienttelemetry.TagName;
import com.azure.cosmos.implementation.directconnectivity.Protocol;
import com.azure.cosmos.implementation.directconnectivity.ReflectionUtils;
import io.netty.handler.ssl.SslContext;
import org.testng.annotations.Test;

import java.util.EnumSet;
Expand Down Expand Up @@ -71,8 +73,45 @@ public void getMetricsConfig() {
}

@Test(groups = { "emulator" })
public void allowUseHttpForVNextEmulator() {
public void httpConnectionWithoutTLSAllowed() {
Configs config = new Configs();
assertThat(config.isInsecureEmulatorConnectionAllowed()).isFalse();
assertThat(config.isHttpConnectionWithoutTLSAllowed()).isFalse();

System.setProperty("COSMOS.HTTP_CONNECTION_WITHOUT_TLS_ALLOWED", "true");
assertThat(config.isHttpConnectionWithoutTLSAllowed()).isTrue();

System.clearProperty("COSMOS.HTTP_CONNECTION_WITHOUT_TLS_ALLOWED");
}

@Test(groups = { "emulator" })
public void emulatorCertValidationDisabled() {
Configs config = new Configs();
assertThat(config.isEmulatorServerCertValidationDisabled()).isFalse();

System.setProperty("COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED", "true");
assertThat(config.isEmulatorServerCertValidationDisabled()).isTrue();

System.clearProperty("COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED");
}

@Test(groups = { "emulator" })
public void emulatorHost() {
Configs config = new Configs();
assertThat(config.getEmulatorHost()).isEmpty();

System.setProperty("COSMOS.EMULATOR_HOST", "randomHost");
assertThat(config.getEmulatorHost()).isEqualTo("randomHost");

System.clearProperty("COSMOS.EMULATOR_HOST");
}

@Test(groups = { "emulator" })
public void sslContextTest() {
Configs config = new Configs();
SslContext sslContext = config.getSslContext(false);
assertThat(sslContext).isEqualTo(ReflectionUtils.getSslContext(config));

sslContext = config.getSslContext(true);
assertThat(sslContext).isEqualTo(ReflectionUtils.getSslContextWithCertValidationDisabled(config));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public void connectionStateListener_OnConnectionEvent(
SslContext sslContext = SslContextUtils.CreateSslContext("client.jks", false);

Configs config = Mockito.mock(Configs.class);
Mockito.doReturn(sslContext).when(config).getSslContext();
Mockito.doReturn(sslContext).when(config).getSslContext(false);

RntbdTransportClient client = new RntbdTransportClient(
config,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.azure.cosmos.implementation.ApiType;
import com.azure.cosmos.implementation.AsyncDocumentClient;
import com.azure.cosmos.implementation.ClientSideRequestStatistics;
import com.azure.cosmos.implementation.Configs;
import com.azure.cosmos.implementation.ConnectionPolicy;
import com.azure.cosmos.implementation.DiagnosticsProvider;
import com.azure.cosmos.implementation.DocumentCollection;
Expand Down Expand Up @@ -44,6 +45,7 @@
import com.azure.cosmos.implementation.throughputControl.controller.request.GlobalThroughputRequestController;
import com.azure.cosmos.implementation.throughputControl.controller.request.PkRangesThroughputRequestController;
import com.azure.cosmos.models.CosmosClientTelemetryConfig;
import io.netty.handler.ssl.SslContext;
import org.apache.commons.lang3.reflect.FieldUtils;

import java.lang.ref.WeakReference;
Expand Down Expand Up @@ -451,4 +453,11 @@ public static ISessionContainer getSessionContainer(RxDocumentClientImpl rxDocum
return get(ISessionContainer.class, rxDocumentClient, "sessionContainer");
}

public static SslContext getSslContext(Configs configs) {
return get(SslContext.class, configs, "sslContext");
}

public static SslContext getSslContextWithCertValidationDisabled(Configs configs) {
return get(SslContext.class, configs, "sslContextWithCertValidationDisabled");
}
}
5 changes: 4 additions & 1 deletion sdk/cosmos/azure-cosmos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
* Enable `JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS` by default for objectMapper. - See [PR 42520](https://github.com/Azure/azure-sdk-for-java/pull/42520)
* Added system property `COSMOS.ALLOW_UNQUOTED_CONTROL_CHARS` which allow customer to disable/enable `JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS`. - See [PR 42520](https://github.com/Azure/azure-sdk-for-java/pull/42520)
* Added system property `COSMOS.CHARSET_DECODER_ERROR_ACTION_ON_MALFORMED_INPUT` and `COSMOS.CHARSET_DECODER_ERROR_ACTION_ON_UNMAPPED_CHARACTER` to allow user config error action on invalid UTF-8 bytes. - See [PR 42520](https://github.com/Azure/azure-sdk-for-java/pull/42520)
* Added system property `COSMOS.INSECURE_EMULATOR_CONNECTION_ALLOWED` and system variable `COSMOS_INSECURE_EMULATOR_CONNECTION_ALLOWED` to allow using insecure connections to connect to CosmosDB emulator. - See [PR 42912](https://github.com/Azure/azure-sdk-for-java/pull/42912)
* Added system property `COSMOS.HTTP_CONNECTION_WITHOUT_TLS_ALLOWED` and system variable `COSMOS_HTTP_CONNECTION_WITHOUT_TLS_ALLOWED` to allow using http connections to connect to CosmosDB emulator. - See [PR 42972](https://github.com/Azure/azure-sdk-for-java/pull/42972)
* **NOTE :** Please only use this config during local development or test environment, do not use this in prod env.
* Added system property `COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED` and system variable `COSMOS_EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED` to disable server certification validation to CosmosDB emulator. - See [PR 42972](https://github.com/Azure/azure-sdk-for-java/pull/42972)
* **NOTE :** Please only use this config during local development or test environment, do not use this in prod env.
* Added system property `COSMOS.EMULATOR_HOST` and system variable `COSMOS_EMULATOR_HOST` to config emulator host name. - See [PR 42972](https://github.com/Azure/azure-sdk-for-java/pull/42972)

### 4.63.4 (2024-10-15)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ public class CosmosClientBuilder implements
private final List<CosmosOperationPolicy> requestPolicies;
private CosmosItemSerializer defaultCustomSerializer;
private boolean isRegionScopedSessionCapturingEnabled = false;
private boolean serverCertValidationDisabled = false;

/**
* Instantiates a new Cosmos client builder.
Expand Down Expand Up @@ -1265,17 +1266,22 @@ ConnectionPolicy buildConnectionPolicy() {
this.connectionPolicy.setEndpointDiscoveryEnabled(this.endpointDiscoveryEnabled);
this.connectionPolicy.setMultipleWriteRegionsEnabled(this.multipleWriteRegionsEnabled);
this.connectionPolicy.setReadRequestsFallbackEnabled(this.readRequestsFallbackEnabled);
this.connectionPolicy.setServerCertValidationDisabled(this.serverCertValidationDisabled);
return this.connectionPolicy;
}

private void validateConfig() {
void validateConfig() {
URI uri;
try {
uri = new URI(serviceEndpoint);
if (!Strings.isNullOrEmpty(uri.getPath()) || !Strings.isNullOrEmpty(uri.getQuery())) {
serviceEndpoint = uri.getScheme() + "://" + uri.getAuthority() + "/";
uri = new URI(serviceEndpoint);
}

if (Configs.isEmulatorServerCertValidationDisabled() && isEmulatorHost(uri)) {
this.serverCertValidationDisabled = true;
}
} catch (URISyntaxException e) {
throw new IllegalArgumentException("invalid serviceEndpoint", e);
}
Expand Down Expand Up @@ -1327,6 +1333,17 @@ CosmosClientBuilder configs(Configs configs) {
return this;
}

private boolean isEmulatorHost(URI uri) {
if (StringUtils.isNotEmpty(Configs.getEmulatorHost())) {
return Configs.getEmulatorHost().equals(uri.getHost());
}

return "localhost".equalsIgnoreCase(uri.getHost())
|| "[::1]".equals(uri.getHost())
|| "127.0.0.1".equals(uri.getHost())
|| "[0:0:0:0:0:0:0:1]".equals(uri.getHost());
}

private void ifThrowIllegalArgException(boolean value, String error) {
if (value) {
throw new IllegalArgumentException(error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class Configs {
public static final String SPECULATION_THRESHOLD = "COSMOS_SPECULATION_THRESHOLD";
public static final String SPECULATION_THRESHOLD_STEP = "COSMOS_SPECULATION_THRESHOLD_STEP";
private final SslContext sslContext;
private final SslContext sslContextWithCertValidationDisabled;

// The names we use are consistent with the:
// * Azure environment variable naming conventions documented at https://azure.github.io/azure-sdk/java_implementation.html and
Expand Down Expand Up @@ -258,27 +259,41 @@ public class Configs {
private static final String COSMOS_DISABLE_IMDS_ACCESS = "COSMOS.DISABLE_IMDS_ACCESS";
private static final String COSMOS_DISABLE_IMDS_ACCESS_VARIABLE = "COSMOS_DISABLE_IMDS_ACCESS";
private static final boolean COSMOS_DISABLE_IMDS_ACCESS_DEFAULT = false;
// Config to indicate whether allow insecure connections, for example allow http connection or disable cert verification

// Config to indicate whether allow http connections
// Please note that this config should only during development or test, please do not use in prod env
private static final boolean DEFAULT_HTTP_CONNECTION_WITHOUT_TLS_ALLOWED = false;
private static final String HTTP_CONNECTION_WITHOUT_TLS_ALLOWED = "COSMOS.HTTP_CONNECTION_WITHOUT_TLS_ALLOWED";
private static final String HTTP_CONNECTION_WITHOUT_TLS_ALLOWED_VARIABLE = "COSMOS_HTTP_CONNECTION_WITHOUT_TLS_ALLOWED";

// Config to indicate whether disable server certificate validation for emulator
// Please note that this config should only during development or test, please do not use in prod env
private static final boolean DEFAULT_INSECURE_EMULATOR_CONNECTION_ALLOWED = false;
private static final String INSECURE_EMULATOR_CONNECTION_ALLOWED = "COSMOS.INSECURE_EMULATOR_CONNECTION_ALLOWED";
private static final String INSECURE_EMULATOR_CONNECTION_ALLOWED_VARIABLE = "COSMOS_INSECURE_EMULATOR_CONNECTION_ALLOWED";
private static final boolean DEFAULT_EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED = false;
private static final String EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED = "COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED";
private static final String EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED_VARIABLE = "COSMOS_EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED";

// Config to indicate emulator host name
// Please note that this config should only during development or test, please do not use in prod env
private static final String DEFAULT_EMULATOR_HOST = StringUtils.EMPTY;
private static final String EMULATOR_HOST = "COSMOS.EMULATOR_HOST";
private static final String EMULATOR_HOST_VARIABLE = "COSMOS_EMULATOR_HOST";

public Configs() {
this.sslContext = sslContextInit();
this.sslContext = sslContextInit(false);
this.sslContextWithCertValidationDisabled = sslContextInit(true);
}

public static int getCPUCnt() {
return CPU_CNT;
}

private SslContext sslContextInit() {
private SslContext sslContextInit(boolean serverCertVerificationDisabled) {
try {
SslContextBuilder sslContextBuilder =
SslContextBuilder
.forClient()
.sslProvider(SslContext.defaultClientProvider());
if (isInsecureEmulatorConnectionAllowed()) {
if (serverCertVerificationDisabled) {
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE); // disable cert verification
}

Expand All @@ -289,8 +304,8 @@ private SslContext sslContextInit() {
}
}

public SslContext getSslContext() {
return this.sslContext;
public SslContext getSslContext(boolean serverCertValidationDisabled) {
return serverCertValidationDisabled ? this.sslContextWithCertValidationDisabled : this.sslContext;
}

public Protocol getProtocol() {
Expand Down Expand Up @@ -840,13 +855,31 @@ public static boolean shouldDisableIMDSAccess() {
return Boolean.parseBoolean(shouldDisableIMDSAccess);
}

public static boolean isInsecureEmulatorConnectionAllowed() {
public static boolean isHttpConnectionWithoutTLSAllowed() {
String httpForEmulatorAllowed = System.getProperty(
INSECURE_EMULATOR_CONNECTION_ALLOWED,
HTTP_CONNECTION_WITHOUT_TLS_ALLOWED,
firstNonNull(
emptyToNull(System.getenv().get(INSECURE_EMULATOR_CONNECTION_ALLOWED_VARIABLE)),
String.valueOf(DEFAULT_INSECURE_EMULATOR_CONNECTION_ALLOWED)));
emptyToNull(System.getenv().get(HTTP_CONNECTION_WITHOUT_TLS_ALLOWED_VARIABLE)),
String.valueOf(DEFAULT_HTTP_CONNECTION_WITHOUT_TLS_ALLOWED)));

return Boolean.parseBoolean(httpForEmulatorAllowed);
}

public static boolean isEmulatorServerCertValidationDisabled() {
String certVerificationDisabledConfig = System.getProperty(
EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED,
firstNonNull(
emptyToNull(System.getenv().get(EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED_VARIABLE)),
String.valueOf(DEFAULT_EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED)));

return Boolean.parseBoolean(certVerificationDisabledConfig);
}

public static String getEmulatorHost() {
return System.getProperty(
EMULATOR_HOST,
firstNonNull(
emptyToNull(System.getenv().get(EMULATOR_HOST_VARIABLE)),
DEFAULT_EMULATOR_HOST));
xinlian12 marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public final class ConnectionPolicy {
private int minConnectionPoolSizePerEndpoint;
private int openConnectionsConcurrency;
private int aggressiveWarmupConcurrency;
private boolean serverCertValidationDisabled = false;

/**
* Constructor.
Expand Down Expand Up @@ -612,6 +613,28 @@ public String getExcludedRegionsAsString() {
return "[]";
}

/***
* Flag to indicate whether disable server cert validation.
* Should only be used in local develop or test environment against emulator.
*
* @param serverCertValidationDisabled flag to indicate whether disable server cert verification.
* @return the ConnectionPolicy.
*/
public ConnectionPolicy setServerCertValidationDisabled(boolean serverCertValidationDisabled) {
this.serverCertValidationDisabled = serverCertValidationDisabled;
return this;
}

/**
* Get the value to indicate whether disable server cert verification.
* Should only be used in local develop or test environment.
*
* @return {@code true} if server cert verification is disabled; {@code false} otherwise.
*/
public boolean isServerCertValidationDisabled() {
return this.serverCertValidationDisabled;
}

@Override
public String toString() {
return "ConnectionPolicy{" +
Expand Down
Loading
Loading