This commit is contained in:
Ohad Bitton 2023-04-17 12:55:47 +03:00
Родитель efaec3dd5c e478801857
Коммит 3bacb12e2d
6 изменённых файлов: 81 добавлений и 9 удалений

Просмотреть файл

@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Fixed
* Replace non-ascii characters in headers to be in line with the service.
### Security
* No redirects by default
## [4.0.4] - 2023-02-20
### Added
- Add new trident endpoint support

Просмотреть файл

@ -347,6 +347,8 @@ class ClientImpl implements Client, StreamingClient {
activityId, activityId, activityId, clientRequestId);
headers.put("x-ms-activitycontext", activityContext);
// replace non-ascii characters in header values with '?'
headers.replaceAll((_i, v) -> v == null ? null : v.replaceAll("[^\\x00-\\x7F]", "?"));
return headers;
}

Просмотреть файл

@ -37,7 +37,8 @@ public class HttpClientFactory {
.setMaxConnTotal(properties.maxConnectionTotal())
.setMaxConnPerRoute(properties.maxConnectionRoute())
.evictExpiredConnections()
.evictIdleConnections(properties.maxIdleTime(), TimeUnit.SECONDS);
.evictIdleConnections(properties.maxIdleTime(), TimeUnit.SECONDS)
.disableRedirectHandling();
if (properties.isKeepAlive()) {
final ConnectionKeepAliveStrategy keepAliveStrategy = new CustomConnectionKeepAliveStrategy(properties.maxKeepAliveTime());

Просмотреть файл

@ -26,6 +26,11 @@ public class UriUtils {
return setPathForUri(uri, path, false);
}
public static String appendPathToUri(String uri, String path) throws URISyntaxException {
String existing = new URIBuilder(uri).getPath();
return setPathForUri(uri, StringUtils.appendIfMissing(existing == null ? "" : existing, "/") + path);
}
public static boolean isLocalAddress(String host) {
if (host.equals("localhost")
|| host.equals("127.0.0.1")

Просмотреть файл

@ -3,16 +3,16 @@ package com.microsoft.azure.kusto.data.auth;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.kusto.data.HttpClientFactory;
import com.microsoft.azure.kusto.data.UriUtils;
import com.microsoft.azure.kusto.data.Utils;
import com.microsoft.azure.kusto.data.exceptions.DataServiceException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jetbrains.annotations.Nullable;
@ -90,9 +90,9 @@ public class CloudInfo {
CloudInfo result;
try {
HttpClient localHttpClient = givenHttpClient == null ? HttpClients.createSystem() : givenHttpClient;
HttpClient localHttpClient = givenHttpClient == null ? HttpClientFactory.create(null) : givenHttpClient;
try {
HttpGet request = new HttpGet(UriUtils.setPathForUri(clusterUrl, METADATA_ENDPOINT));
HttpGet request = new HttpGet(UriUtils.appendPathToUri(clusterUrl, METADATA_ENDPOINT));
request.addHeader(HttpHeaders.ACCEPT_ENCODING, "gzip,deflate");
request.addHeader(HttpHeaders.ACCEPT, "application/json");
HttpResponse response = localHttpClient.execute(request);

Просмотреть файл

@ -3,12 +3,21 @@
package com.microsoft.azure.kusto.ingest;
import com.microsoft.azure.kusto.data.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.microsoft.azure.kusto.data.Client;
import com.microsoft.azure.kusto.data.ClientFactory;
import com.microsoft.azure.kusto.data.ClientRequestProperties;
import com.microsoft.azure.kusto.data.HttpClientProperties;
import com.microsoft.azure.kusto.data.KustoOperationResult;
import com.microsoft.azure.kusto.data.KustoResultSetTable;
import com.microsoft.azure.kusto.data.StreamingClient;
import com.microsoft.azure.kusto.data.Utils;
import com.microsoft.azure.kusto.data.auth.CloudInfo;
import com.microsoft.azure.kusto.data.auth.ConnectionStringBuilder;
import com.microsoft.azure.kusto.data.auth.endpoints.KustoTrustedEndpoints;
import com.microsoft.azure.kusto.data.auth.endpoints.MatchRule;
import com.microsoft.azure.kusto.data.exceptions.DataClientException;
import com.microsoft.azure.kusto.data.exceptions.DataServiceException;
import com.microsoft.azure.kusto.data.format.CslDateTimeFormat;
@ -24,6 +33,7 @@ import com.microsoft.azure.kusto.ingest.source.StreamSourceInfo;
import com.microsoft.azure.kusto.ingest.utils.ContainerWithSas;
import com.microsoft.azure.kusto.ingest.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.http.impl.client.CloseableHttpClient;
@ -119,6 +129,7 @@ class E2ETest {
ConnectionStringBuilder engineCsb = ConnectionStringBuilder.createWithAadApplicationCredentials(System.getenv("ENGINE_CONNECTION_STRING"), appId,
appKey, tenantId);
engineCsb.setUserNameForTracing("Java_E2ETest_ø");
try {
streamingIngestClient = IngestClientFactory.createStreamingIngestClient(engineCsb);
queryClient = ClientFactory.createClient(engineCsb);
@ -550,10 +561,58 @@ class E2ETest {
Mockito.verify(httpClientSpy, atLeast(2)).execute(any());
}
@Test
void testNoRedirectsCloudFail() {
KustoTrustedEndpoints.addTrustedHosts(List.of(new MatchRule("statusreturner.azurewebsites.net", false)), false);
List<Integer> redirectCodes = Arrays.asList(301, 302, 307, 308);
redirectCodes.parallelStream().map(code -> {
try (Client client = ClientFactory.createClient(
ConnectionStringBuilder.createWithAadAccessTokenAuthentication("https://statusreturner.azurewebsites.net/nocloud/" + code, "token"))) {
try {
client.execute("db", "table");
Assertions.fail("Expected exception");
} catch (DataServiceException e) {
Assertions.assertTrue(e.getMessage().contains("" + code));
Assertions.assertTrue(e.getMessage().contains("metadata"));
}
} catch (Exception e) {
return e;
}
return null;
}).forEach(e -> {
if (e != null) {
Assertions.fail(e);
}
});
}
@Test
void testNoRedirectsClientFail() {
KustoTrustedEndpoints.addTrustedHosts(List.of(new MatchRule("statusreturner.azurewebsites.net", false)), false);
List<Integer> redirectCodes = Arrays.asList(301, 302, 307, 308);
redirectCodes.parallelStream().map(code -> {
try (Client client = ClientFactory.createClient(
ConnectionStringBuilder.createWithAadAccessTokenAuthentication("https://statusreturner.azurewebsites.net/" + code, "token"))) {
try {
client.execute("db", "table");
Assertions.fail("Expected exception");
} catch (DataServiceException e) {
Assertions.assertTrue(e.getMessage().contains("" + code));
Assertions.assertFalse(e.getMessage().contains("metadata"));
}
} catch (Exception e) {
return e;
}
return null;
}).forEach(e -> {
if (e != null) {
Assertions.fail(e);
}
});
}
@Test
void testStreamingIngestFromBlob() throws IngestionClientException, IngestionServiceException, IOException {
ConnectionStringBuilder engineCsb = ConnectionStringBuilder.createWithAadApplicationCredentials(System.getenv("ENGINE_CONNECTION_STRING"), appId,
appKey, tenantId);
ResourceManager resourceManager = new ResourceManager(dmCslClient, null);
ContainerWithSas container = resourceManager.getTempStorage();
AzureStorageClient azureStorageClient = new AzureStorageClient();
@ -577,6 +636,5 @@ class E2ETest {
assertRowCount(item.rows, false);
}
}
}
}