Configure HTTPS in CloudCode

By default, the standard fetch API should be sufficient to connect to most external APIs.

However, there are some scenarios where:

  1. The server uses self-signed certificates.

  2. The server only allows incoming connections from a specific list of IP addresses or ranges.

These cases require a little more configuration.

Self-signed Certificates

If a connection can be made to the server directly with a browser, or a tool such as curl, there is typically no further configuration required.

If the certificate is self-signed or uses an untrusted root, a custom https Agent must be configured to allow the connection.

A simple example to allow all insecure requests:

const https = require('https');

const agent = https.Agent({
  // This allows ANY certificate - dangerous! Only use for testing
  rejectUnauthorized: false
});

const response = await fetch('https://self-signed.badssl.com/', { agent });

The above works as a quick test, but is not secure at all - almost as bad as using plain HTTP.

A better solution is to export the Certificate Authority, and trust this in the script. The certificate chain can be exported by visiting the site in a browser, viewing the certificate details, and exporting it as a PEM (base64) file.

Alternatively, the certificate chain may be provided by the server administrator. Note that only the public certificate is required - the private key must never leave the server.

const fs = require('fs');
const https = require('https');

const agent = https.Agent({
  ca: fs.readFileSync(require.resolve('./my-ca.pem')) // Reference to the exported certificate chain
});

const response = await fetch('https://self-signed.badssl.com/', { agent });

IP Whitelisting

CloudCode uses dynamic IP addresses and does not have a fixed IP address range that can be whitelisted.

To work around this issue, JourneyApps provides a proxy server with a fixed set of IP addresses when required.

Contact JourneyApps Support to get credentials for the proxy server for a specific app. The following info is required:

  1. The host and port to connect to, e.g. https://my-server.test:8443.

  2. A link to the app that will use the proxy server.

You will then be provided with credentials, which can be used as follows in the CloudCode task.

To use this, you will need to add the @journeyapps/https-proxy-socket package as a dependency to your task. See Dependencies for more detailed instructions.

You can then configure and use the proxy from the task:

const { HttpsProxySocket } = require('@journeyapps/https-proxy-socket');

const proxy = new HttpsProxySocket('https://us-cc-proxy.journeyapps.com', {
  auth: '' // Token as provided by JourneyApps Support.
});

const agent = proxy.agent();

const response = await fetch('https://my-host.com/', { agent });

Proxy with self-signed certificates

Both self-signed certificates and the proxy use the agent option. To specify custom certificates or TLS options when using the proxy, pass the options to the proxy.agent() call, instead of creating a new https.Agent:

const { HttpsProxySocket } = require('@journeyapps/https-proxy-socket');

const proxy = new HttpsProxySocket('https://us-cc-proxy.journeyapps.com', {
  auth: '' // Token as provided by JourneyApps Support.
});

const agent = proxy.agent({
  ca: fs.readFileSync(require.resolve('./my-ca.pem'))
  // OR (dangerous - only for testing!)
  // rejectUnauthorized: false
});

const response = await fetch('https://my-host.com/', { agent });

Resources

More options are available on the @journeyapps/https-proxy-socket package.

Any of these options can be passed to the agent, both https.Agent and HttpsProxySocket#agent:

Last updated