Croway commented on code in PR #29249:
URL: https://github.com/apache/camel/pull/29249#discussion_r4493118134


##########
test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/services/AzureCosmosDbInfraService.java:
##########
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.services;
+
+import org.apache.camel.test.infra.common.services.InfrastructureService;
+
+/**
+ * A Cosmos DB for NoSQL account
+ */
+public interface AzureCosmosDbInfraService extends InfrastructureService {
+
+    /**
+     * The endpoint of the account (the databaseEndpoint option of the 
azure-cosmosdb component)
+     */
+    String endpoint();
+
+    /**
+     * The key of the account (the accountKey option of the azure-cosmosdb 
component)
+     */
+    String accessKey();

Review Comment:
   `camel infra run azure cosmos-db` prints only what this interface declares 
(`InfraRun` reflects over its declared methods): `{accessKey=C2y6..., 
endpoint=https://localhost:32986/devstoreaccount1-cosmos}`, not 
`certificateUrl()`. A route can't connect with those two values. Against the 
service of this PR:
   
   - the component's own client (`databaseEndpoint` + `accountKey`, no 
`cosmosAsyncClient`) fails when it is built: `Client initialization failed ... 
SSLHandshakeException ... PKIX path building failed`;
   - with the Floci AZ CA trusted by the JVM, `createDatabase` fails with 501 
`This operation is not supported by the floci-az Cosmos DB emulator.` on `GET 
/addresses/?$resolveFor=dbs&$filter=protocol eq rntbd`. `CosmosDbClientFactory` 
always builds a direct-mode client, and `CosmosDbConfiguration` has no option 
for the connection mode;
   - the same client with `gatewayMode()` (endpoint discovery left on) creates 
a database and a container, and upserts and reads an item.
   
   So only a route that binds its own `cosmosAsyncClient`, built like 
`AzureCosmosDbClientUtils` does, can use the service. Could the PR description 
and the Javadoc say so, and could `certificateUrl()` move to this interface so 
`camel infra run` prints it? A connection-mode option on the component would be 
a JIRA of its own.



##########
components/camel-azure/camel-azure-cosmosdb/src/test/java/org/apache/camel/component/azure/cosmosdb/integration/CosmosDbProducerIT.java:
##########
@@ -191,6 +185,12 @@ void testCreateAndDeleteContainer() throws 
InterruptedException {
     }
 
     @Test
+    @EnabledIfSystemProperties({
+            @EnabledIfSystemProperty(named = "endpoint", matches = ".+",

Review Comment:
   Low: the remote-only tests are gated on `endpoint`/`accessKey`, while the 
service and `AzureCosmosDbClientUtils` follow `azure.instance.type`. With the 
test-infra properties (`-Dazure.instance.type=remote 
-Dazure.cosmosdb.endpoint=... -Dazure.cosmosdb.access.key=...`), no Floci AZ 
container starts and the other 5 tests of this class go to the account, but 
these two are skipped as if Floci AZ were used:
   
   ```
   System property [endpoint] does not exist ==> Floci AZ does not emulate the 
throughput (offers) of the databases: ...
   System property [endpoint] does not exist ==> Floci AZ does not emulate the 
queries of the containers: ...
   ```
   
   The same applies to the remote-only tests of `CosmosDbClientOperationsIT`, 
`CosmosDbDatabaseOperationsIT`, `CosmosDbContainerOperationsIT` and 
`CosmosDbConsumerIT`. Gating them on the instance type would leave one switch, 
since `CosmosDbTestUtils.createService()` already sets it to `remote` for 
`-Dendpoint`/`-DaccessKey`.



##########
test-infra/camel-test-infra-azure-cosmosdb/src/main/java/org/apache/camel/test/infra/azure/cosmosdb/clients/AzureCosmosDbClientUtils.java:
##########
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.camel.test.infra.azure.cosmosdb.clients;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import com.azure.cosmos.CosmosAsyncClient;
+import com.azure.cosmos.CosmosClientBuilder;
+import 
org.apache.camel.test.infra.azure.cosmosdb.common.AzureCosmosDbProperties;
+
+public final class AzureCosmosDbClientUtils {
+    private static final String TRUST_STORE = "javax.net.ssl.trustStore";
+    private static final String TRUST_STORE_TYPE = 
"javax.net.ssl.trustStoreType";
+    private static final String TRUST_STORE_PASSWORD = 
"javax.net.ssl.trustStorePassword";
+    private static final String TRUST_STORE_PROVIDER = 
"javax.net.ssl.trustStoreProvider";
+
+    private AzureCosmosDbClientUtils() {
+
+    }
+
+    /**
+     * Builds a client of the account the tests run against: the local Floci 
AZ container, unless the
+     * {@link AzureCosmosDbProperties#INSTANCE_TYPE} system property is {@code 
remote}. Like the clients the
+     * azure-cosmosdb component builds by default, it returns the items it 
writes.
+     */
+    public static CosmosAsyncClient createAsyncClient() {
+        CosmosClientBuilder builder = new CosmosClientBuilder()
+                .endpoint(System.getProperty(AzureCosmosDbProperties.ENDPOINT))
+                .key(System.getProperty(AzureCosmosDbProperties.ACCESS_KEY))
+                .contentResponseOnWriteEnabled(true);
+
+        String instanceType = 
System.getProperty(AzureCosmosDbProperties.INSTANCE_TYPE);
+        if (instanceType == null || 
instanceType.equals("local-azure-container")) {
+            // Floci AZ emulates the gateway API only, and the client keeps to 
the endpoint whatever locations the
+            // emulator advertises
+            builder.gatewayMode()
+                    .endpointDiscoveryEnabled(false);
+
+            return buildTrusting(builder, 
System.getProperty(AzureCosmosDbProperties.CERTIFICATE_URL));
+        }
+
+        return builder.buildAsyncClient();
+    }
+
+    /*
+     * The Cosmos DB SDK has no option for the certificates a client trusts: a 
client trusts the default trust store of
+     * the JVM, which it loads when it is built. The default trust store holds 
the certificate of the emulator, next to the
+     * certificates the JVM trusts, only while the client is built: the client 
trusts the emulator, and the trust of the
+     * JVM is the same once the client is built.
+     */
+    private static synchronized CosmosAsyncClient 
buildTrusting(CosmosClientBuilder builder, String certificateUrl) {

Review Comment:
   azure-cosmos 4.75.0 has a switch for emulators: with 
`COSMOS.EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED=true` (system property, 
or the env variable `COSMOS_EMULATOR_SERVER_CERTIFICATE_VALIDATION_DISABLED`), 
`CosmosClientBuilder.validateConfig()` turns off certificate validation when 
the endpoint host is `localhost`, `127.0.0.1`, `[::1]` or the 
`COSMOS.EMULATOR_HOST` value, and `Configs.sslContextInit` then uses 
`InsecureTrustManagerFactory`.
   
   Against this PR's service, with only that property, 
`gatewayMode().endpointDiscoveryEnabled(false)` and no trust store, the client 
creates a database and a container, and upserts and reads an item. Without the 
property: `PKIX path building failed`.
   
   It could replace `buildTrusting`: the temporary change of the JVM-wide 
`javax.net.ssl.*` properties, the CA download and the PKCS12 file per client, 
and the reliance on the SDK building its `SslContext` eagerly that gnodet-bot 
noted. `camel infra run` users could set the env variable as well. With a 
remote Docker host, `host()` is not localhost, so `COSMOS.EMULATOR_HOST` would 
be set to it too. The trade-off: the client trusts any certificate of the 
emulator host, not only the Floci AZ CA, which seems fine for a test emulator.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to