Skip to content
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
21 changes: 21 additions & 0 deletions src/templates/csharp/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ public enum DeviceSourceEnums { Kobiton, Other }
public const int SendKeysDelayInMs = 1500;
public const int IdleDelayInMs = 3000;
public const string KobitonApiUrl = "{{KobitonApiUrl}}";
// Run with KOBITON_TRUST_ALL_CERTS=true to skip TLS cert validation — needed
// for on-prem standalone deployments served over a self-signed certificate.
public static readonly bool TrustAllCerts = new[] { "1", "true", "yes" }
.Contains((Environment.GetEnvironmentVariable("KOBITON_TRUST_ALL_CERTS") ?? "").Trim().ToLower());
{{kobitonCredential}}

public static string GetAppiumServerUrlWithAuth()
Expand All @@ -38,6 +42,23 @@ public static string GetBasicAuthString()
return "Basic " + authEncString;
}

// Returns an HttpClient that trusts any TLS certificate when TrustAllCerts
// is enabled; otherwise a default client that validates certificates
// normally. Used by the proxy and all Kobiton REST clients.
public static HttpClient CreateHttpClient()
{
if (!TrustAllCerts)
{
return new HttpClient();
}

var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
};
return new HttpClient(handler);
}

{{desiredCaps}}
}
}
2 changes: 1 addition & 1 deletion src/templates/csharp/OtpService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace AppiumTest

public class OtpService
{
private static readonly HttpClient httpClient = new HttpClient();
private static readonly HttpClient httpClient = Config.CreateHttpClient();

public const int FindPhoneNumberMaxAttempts = 12;
public const int FindPhoneNumberInternalInMs = 10000;
Expand Down
2 changes: 1 addition & 1 deletion src/templates/csharp/ProxyServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private void HandleRequest(HttpListenerContext context, string appiumServerUrl)

var url = new Uri(appiumServerUrl + urlString);

using (var client = new HttpClient())
using (var client = Config.CreateHttpClient())
{
var httpRequest = new HttpRequestMessage
{
Expand Down
3 changes: 3 additions & 0 deletions src/templates/csharp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ This project is generated by Scriptless Automation based on an exploratory sessi
## Commands

- Execute tests: `dotnet test --logger "console;verbosity=normal"`
- On a Kobiton Standalone server using a self-signed SSL certificate, skip TLS cert validation with `KOBITON_TRUST_ALL_CERTS=true`:
- macOS/Linux: `KOBITON_TRUST_ALL_CERTS=true dotnet test --logger "console;verbosity=normal"`
- Windows (PowerShell): `$env:KOBITON_TRUST_ALL_CERTS="true"; dotnet test --logger "console;verbosity=normal"`

## View the test results

Expand Down
6 changes: 3 additions & 3 deletions src/templates/csharp/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public enum PressTypes
public Point? screenSize;
public double retinaScale;
public string deviceName, platformVersion;
public HttpClient httpClient = new HttpClient();
public HttpClient httpClient = Config.CreateHttpClient();
private string? currentContext;
private string currentWindow;

Expand Down Expand Up @@ -1379,7 +1379,7 @@ public void SetCurrentCommandId(long currentCommandId)
public string GetAppUrl(int appVersionId)
{
string appUrl = string.Empty;
using (HttpClient client = new HttpClient())
using (HttpClient client = Config.CreateHttpClient())
{
client.DefaultRequestHeaders.Add("Content-Type", "application/json");
client.DefaultRequestHeaders.Add("Authorization", Config.GetBasicAuthString());
Expand Down Expand Up @@ -1495,7 +1495,7 @@ public async Task<Device> GetAvailableDevice(AppiumOptions capabilities)
};
deviceListUriBuilder.Query = new FormUrlEncodedContent(query).ReadAsStringAsync().Result;

using (var httpClient = new HttpClient())
using (var httpClient = Config.CreateHttpClient())
{
httpClient.DefaultRequestHeaders.Add(HttpRequestHeader.Authorization.ToString(),
Config.GetBasicAuthString());
Expand Down
39 changes: 39 additions & 0 deletions src/templates/java/Config.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package com.kobiton.scriptlessautomation;

import okhttp3.OkHttpClient;
import org.apache.commons.codec.binary.Base64;
import org.openqa.selenium.remote.DesiredCapabilities;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Arrays;

public class Config {
enum DEVICE_SOURCE_ENUMS {KOBITON, OTHER}
Expand All @@ -19,6 +26,10 @@ enum DEVICE_SOURCE_ENUMS {KOBITON, OTHER}
public static final int SEND_KEYS_DELAY_IN_MS = 1500;
public static final int IDLE_DELAY_IN_MS = 3000;
public static final String KOBITON_API_URL = "{{kobiton_api_url}}";
// Run with KOBITON_TRUST_ALL_CERTS=true to skip TLS cert validation — needed
// for on-prem standalone deployments served over a self-signed certificate.
public static final boolean TRUST_ALL_CERTS = Arrays.asList("1", "true", "yes")
.contains(String.valueOf(System.getenv("KOBITON_TRUST_ALL_CERTS")).trim().toLowerCase());
{{kobitonCredential}}

public static String getAppiumServerUrlWithAuth() throws MalformedURLException {
Expand All @@ -34,5 +45,33 @@ public static String getBasicAuthString() {
return "Basic " + authEncString;
}

// Returns an OkHttpClient builder that trusts any TLS certificate when
// TRUST_ALL_CERTS is enabled; otherwise a default builder that validates
// certificates normally. Used by the proxy and all Kobiton REST clients.
public static OkHttpClient.Builder createHttpClientBuilder() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (!TRUST_ALL_CERTS) {
return builder;
}

try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) {}
public void checkServerTrusted(X509Certificate[] chain, String authType) {}
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new SecureRandom());
builder.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier((hostname, session) -> true);
} catch (Exception e) {
throw new RuntimeException("Failed to build trust-all SSL context", e);
}

return builder;
}

{{desiredCaps}}
}
2 changes: 1 addition & 1 deletion src/templates/java/OtpService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class OtpService {
public static final int FIND_OTP_CODE_MAX_ATTEMPTS = 12;
public static final int FIND_OTP_CODE_INTERVAL_IN_MS = 10000;

private final OkHttpClient httpClient = new OkHttpClient();
private final OkHttpClient httpClient = Config.createHttpClientBuilder().build();

public String countryCode = "1";
public String rawPhoneNumber;
Expand Down
2 changes: 1 addition & 1 deletion src/templates/java/ProxyServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class ProxyServer extends NanoHTTPD {
private final int socketTimeoutInSecond = 15 * 60;
private boolean forceW3C = false;

private final OkHttpClient httpClient = new OkHttpClient.Builder()
private final OkHttpClient httpClient = Config.createHttpClientBuilder()
.connectTimeout(socketTimeoutInSecond, TimeUnit.SECONDS)
.writeTimeout(socketTimeoutInSecond, TimeUnit.SECONDS)
.readTimeout(socketTimeoutInSecond, TimeUnit.SECONDS)
Expand Down
5 changes: 4 additions & 1 deletion src/templates/java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ This project is generated by Scriptless Automation based on an exploratory sessi
## Commands

- Build project: `mvn clean install -DskipTests`
- Execute tests: `mvn test` or `mvn test -Djavax.net.ssl.trustStoreType=KeychainStore` on Kobiton Standalone environment
- Execute tests: `mvn test`
- On a Kobiton Standalone server using a self-signed SSL certificate, skip TLS cert validation with `KOBITON_TRUST_ALL_CERTS=true`:
- macOS/Linux: `KOBITON_TRUST_ALL_CERTS=true mvn test`
- Windows (PowerShell): `$env:KOBITON_TRUST_ALL_CERTS="true"; mvn test`

## View the test results

Expand Down
4 changes: 2 additions & 2 deletions src/templates/java/TestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public class TestBase {
enum PRESS_TYPES {HOME, BACK, POWER, APP_SWITCH, ENTER, DELETE}

public Gson gson = new GsonBuilder().disableHtmlEscaping().create();
public final OkHttpClient httpClient = new OkHttpClient();
public final OkHttpClient httpClient = Config.createHttpClientBuilder().build();

private String currentContext;
private String currentWindow;
Expand Down Expand Up @@ -1182,7 +1182,7 @@ public Device findOnlineDevice(DesiredCapabilities capabilities) throws Exceptio

public String getAppUrl(int appVersionId) throws Exception {
String appUrl = "";
OkHttpClient client = new OkHttpClient();
OkHttpClient client = Config.createHttpClientBuilder().build();
Request request = new Request.Builder()
.url(String.format("%s/v1/app/versions/%s/downloadUrl", Config.KOBITON_API_URL, appVersionId))
.addHeader(HttpHeaders.CONTENT_TYPE, "application/json")
Expand Down
5 changes: 4 additions & 1 deletion src/templates/nodejs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ This project is generated by Scriptless Automation based on an exploratory sessi
## Commands

- Install dependent modules: `npm install`
- Execute tests: `npm test` or `NODE_TLS_REJECT_UNAUTHORIZED=0 npm test` on Kobiton Standalone environment
- Execute tests: `npm test`
- On a Kobiton Standalone server using a self-signed SSL certificate, skip TLS cert validation with `KOBITON_TRUST_ALL_CERTS=true`:
- macOS/Linux: `KOBITON_TRUST_ALL_CERTS=true npm test`
- Windows (PowerShell): `$env:KOBITON_TRUST_ALL_CERTS="true"; npm test`

## View the test results

Expand Down
3 changes: 3 additions & 0 deletions src/templates/nodejs/src/test/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export const Config = {
SEND_KEYS_DELAY_IN_MS: 1500,
IDLE_DELAY_IN_MS: 3000,
KOBITON_API_URL: '{{kobitonApiUrl}}',
// Run with KOBITON_TRUST_ALL_CERTS=true to skip TLS cert validation — needed
// for on-prem standalone deployments served over a self-signed certificate.
TRUST_ALL_CERTS: ['1', 'true', 'yes'].includes((process.env.KOBITON_TRUST_ALL_CERTS || '').trim().toLowerCase()),

getAppiumServerUrlWithAuth() {
const url = new URL(this.APPIUM_SERVER_URL)
Expand Down
7 changes: 7 additions & 0 deletions src/templates/nodejs/src/test/helper/base.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import BPromise from 'bluebird'
import canvas from 'canvas'
import axios from 'axios'
import https from 'https'
import path from 'path'
import get from 'lodash/get'
import flatten from 'lodash/flatten'
Expand All @@ -15,6 +16,12 @@ import Point from './point'
import {Config} from '../config'
import {DEVICE_SOURCES, PRESS_TYPES} from './constants'

// Skip TLS cert validation on the direct Kobiton REST calls when
// KOBITON_TRUST_ALL_CERTS is set — needed for standalone self-signed certs.
if (Config.TRUST_ALL_CERTS) {
axios.defaults.httpsAgent = new https.Agent({rejectUnauthorized: false})
}

const NATIVE_CONTEXT = 'NATIVE_APP'
const PLATFORM_NAMES = {
IOS: 'IOS',
Expand Down
2 changes: 1 addition & 1 deletion src/templates/nodejs/src/test/helper/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default class Proxy {
req.url = url.toString().replace(this.getServerUrl(), '')
this._proxy.web(req, res, {
target: Config.getAppiumServerUrlWithAuth().replace('/wd/hub', ''),
secure: false,
secure: !Config.TRUST_ALL_CERTS,
changeOrigin: true
})
})
Expand Down
6 changes: 6 additions & 0 deletions src/templates/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ pytest test_suite.py -v -s
Run `deactivate` when finished. On subsequent runs, only `source .venv/bin/activate`
and `pytest test_suite.py -v -s` are needed.

On a Kobiton Standalone server using a self-signed SSL certificate, skip TLS cert
validation with `KOBITON_TRUST_ALL_CERTS=true`:

- macOS/Linux: `KOBITON_TRUST_ALL_CERTS=true pytest test_suite.py -v -s`
- Windows (PowerShell): `$env:KOBITON_TRUST_ALL_CERTS="true"; pytest test_suite.py -v -s`

## View the test results

### Run on Kobiton platform
Expand Down
14 changes: 14 additions & 0 deletions src/templates/python/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from urllib.parse import urlparse
import base64
import os

import requests
from urllib3.exceptions import InsecureRequestWarning

from constants import DeviceSource


Expand All @@ -14,6 +19,9 @@ class Config:
SEND_KEYS_DELAY_IN_MS = 1500
IDLE_DELAY_IN_MS = 3000
KOBITON_API_URL = '{{kobitonApiUrl}}'
# Run with KOBITON_TRUST_ALL_CERTS=true to skip TLS cert validation — needed
# for on-prem standalone deployments served over a self-signed certificate.
TRUST_ALL_CERTS = os.getenv('KOBITON_TRUST_ALL_CERTS', '').strip().lower() in ('1', 'true', 'yes')
{{kobitonCredential}}

#{{desiredCaps}}
Expand All @@ -29,3 +37,9 @@ def get_basic_auth_string(cls):
credentials = f"{cls.API_USERNAME}:{cls.API_KEY}"
encoded = base64.b64encode(credentials.encode()).decode()
return f"Basic {encoded}"


# Suppress the per-request InsecureRequestWarning emitted when TRUST_ALL_CERTS
# disables verification across the proxy and the Kobiton REST calls.
if Config.TRUST_ALL_CERTS:
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
4 changes: 4 additions & 0 deletions src/templates/python/otp_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def fetch():
f"{Config.KOBITON_API_URL}/v1/otp/phone-numbers/available",
params={'countryCode': country_code},
headers={'Authorization': Config.get_basic_auth_string()},
verify=not Config.TRUST_ALL_CERTS,
)
if response.status_code in (401, 403):
raise _AbortRetry(Exception(response.text or f"HTTP {response.status_code}"))
Expand Down Expand Up @@ -87,6 +88,7 @@ def fetch():
response = requests.get(
f"{Config.KOBITON_API_URL}/v1/otp/email-address/available",
headers={'Authorization': Config.get_basic_auth_string()},
verify=not Config.TRUST_ALL_CERTS,
)
if response.status_code in (401, 403):
raise _AbortRetry(Exception(response.text or f"HTTP {response.status_code}"))
Expand Down Expand Up @@ -121,6 +123,7 @@ def fetch():
response = requests.get(
url, params=params,
headers={'Authorization': Config.get_basic_auth_string()},
verify=not Config.TRUST_ALL_CERTS,
)
if response.status_code in (401, 403):
raise _AbortRetry(Exception(response.text or f"HTTP {response.status_code}"))
Expand Down Expand Up @@ -160,6 +163,7 @@ def cleanup(self):
requests.post(
url, params=params,
headers={'Authorization': Config.get_basic_auth_string()},
verify=not Config.TRUST_ALL_CERTS,
)
self.is_cleanup = True
except Exception as e:
Expand Down
11 changes: 1 addition & 10 deletions src/templates/python/proxy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,6 @@

SOCKET_TIMEOUT_SECONDS = 15 * 60

# Set False to enforce upstream TLS cert validation. Default True so on-prem
# standalone deployments with self-signed certs work out of the box.
TRUST_ALL_CERTS = True

if TRUST_ALL_CERTS:
# Avoid an InsecureRequestWarning per forwarded request when verify=False.
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# JSON Wire Protocol status code -> W3C error string.
_ERROR_CODES = {
6: "invalid session id",
Expand Down Expand Up @@ -164,7 +155,7 @@ def serve(self, request_uri, method, request_body):
method, url,
headers=headers, data=request_body,
timeout=SOCKET_TIMEOUT_SECONDS,
verify=not TRUST_ALL_CERTS,
verify=not Config.TRUST_ALL_CERTS,
)
status_code = response.status_code
content_type = response.headers.get('Content-Type', 'application/json')
Expand Down
3 changes: 2 additions & 1 deletion src/templates/python/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def get_app_url(self, app_version_id):
'Content-Type': 'application/json',
}
url = f"{Config.KOBITON_API_URL}/v1/app/versions/{app_version_id}/downloadUrl"
response = requests.get(url, headers=headers)
response = requests.get(url, headers=headers, verify=not Config.TRUST_ALL_CERTS)
response.raise_for_status()
return response.json()['url']

Expand Down Expand Up @@ -704,6 +704,7 @@ def get_available_device(self, capabilities):
f"{Config.KOBITON_API_URL}/v1/devices",
params={k: v for k, v in params.items() if v is not None},
headers={'Authorization': Config.get_basic_auth_string()},
verify=not Config.TRUST_ALL_CERTS,
)
if response.status_code != 200:
raise Exception(response.text)
Expand Down
Loading