UNPKG

aws-crt

Version:

NodeJS/browser bindings to the aws-c-* libraries

249 lines (211 loc) 10.4 kB
/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ import { ClientTlsContext, SocketDomain, SocketOptions, SocketType, TlsContextOptions, } from "./io"; import { HttpClientConnection, HttpHeaders, HttpProxyAuthenticationType, HttpRequest } from "./http"; import {ProxyConfig, ProxyTestType} from "@test/proxy"; import {AwsIotMqttConnectionConfigBuilder} from "./aws_iot"; import {v4 as uuid} from "uuid"; import {MqttClient} from "./mqtt"; import { InputStream } from './io'; import { PassThrough } from "stream"; import { AwsCredentialsProvider, X509CredentialsConfig, AwsSigningConfig, AwsSigningAlgorithm, AwsSignatureType, AwsSignedBodyHeaderType, aws_sign_request } from "./auth"; async function test_proxied_connection(test_type : ProxyTestType, auth_type : HttpProxyAuthenticationType) { const promise = new Promise((resolve, reject) => { let host = ProxyConfig.get_uri_from_test_type(test_type) let connection = new HttpClientConnection( undefined, host, ProxyConfig.get_port_from_test_type(test_type), new SocketOptions(SocketType.STREAM, SocketDomain.IPV4, 3000), ProxyConfig.get_tls_connection_options_for_test(test_type, host), ProxyConfig.create_http_proxy_options_from_environment(test_type, auth_type)); connection.on('connect', () => { let request = new HttpRequest( "GET", '/', new HttpHeaders([ ['host', host], ['user-agent', 'AWS CRT for NodeJS'] ]) ); let stream = connection.request(request); stream.on('response', (status_code, headers) => { expect(status_code).toBe(200); expect(headers).toBeDefined(); }); stream.on('data', (body_data) => { expect(body_data.byteLength).toBeGreaterThan(0); }); stream.on('end', () => { connection.close(); }); stream.on('error', (error) => { connection.close(); console.log(error); expect(error).toBeUndefined(); }); stream.activate(); }); connection.on('close', () => { resolve(true); }); connection.on('error', (error) => { reject(error); }); }); await expect(promise).resolves.toBeTruthy(); } const conditional_test = (condition : boolean) => condition ? it : it.skip; function is_proxy_environment_enabled() { return ProxyConfig.is_valid() } function is_tls_to_proxy_enabled() { return ProxyConfig.is_tls_to_proxy_valid() } function is_x509_enabled() { return ProxyConfig.is_valid() && ProxyConfig.is_tls_to_proxy_valid() && ProxyConfig.is_x509_valid(); } conditional_test(is_proxy_environment_enabled())('Proxied Http Connection Forwarding NoAuth', async () => { await test_proxied_connection(ProxyTestType.FORWARDING, HttpProxyAuthenticationType.None); }); conditional_test(is_proxy_environment_enabled())('Proxied Http Connection Legacy NoAuth', async () => { await test_proxied_connection(ProxyTestType.LEGACY_HTTP, HttpProxyAuthenticationType.None); }); conditional_test(is_proxy_environment_enabled())('Proxied Https Connection Legacy NoAuth', async () => { await test_proxied_connection(ProxyTestType.LEGACY_HTTPS, HttpProxyAuthenticationType.None); }); conditional_test(is_proxy_environment_enabled())('Proxied Http Connection Tunneling NoAuth', async () => { await test_proxied_connection(ProxyTestType.TUNNELING_HTTP, HttpProxyAuthenticationType.None); }); conditional_test(is_proxy_environment_enabled())('Proxied Https Connection Tunneling NoAuth', async () => { await test_proxied_connection(ProxyTestType.TUNNELING_HTTPS, HttpProxyAuthenticationType.None); }); conditional_test(is_proxy_environment_enabled() && is_tls_to_proxy_enabled())('Proxied Https Connection DoubleTls NoAuth', async () => { await test_proxied_connection(ProxyTestType.TUNNELING_DOUBLE_TLS, HttpProxyAuthenticationType.None); }); conditional_test(is_proxy_environment_enabled())('Proxied Http Connection Forwarding BasicAuth', async () => { await test_proxied_connection(ProxyTestType.FORWARDING, HttpProxyAuthenticationType.Basic); }); conditional_test(is_proxy_environment_enabled())('Proxied Http Connection Legacy BasicAuth', async () => { await test_proxied_connection(ProxyTestType.LEGACY_HTTP, HttpProxyAuthenticationType.Basic); }); conditional_test(is_proxy_environment_enabled())('Proxied Https Connection Legacy BasicAuth', async () => { await test_proxied_connection(ProxyTestType.LEGACY_HTTPS, HttpProxyAuthenticationType.Basic); }); conditional_test(is_proxy_environment_enabled())('Proxied Http Connection Tunneling BasicAuth', async () => { await test_proxied_connection(ProxyTestType.TUNNELING_HTTP, HttpProxyAuthenticationType.Basic); }); conditional_test(is_proxy_environment_enabled())('Proxied Https Connection Tunneling BasicAuth', async () => { await test_proxied_connection(ProxyTestType.TUNNELING_HTTPS, HttpProxyAuthenticationType.Basic); }); async function test_proxied_mqtt_connection(test_type : ProxyTestType, auth_type : HttpProxyAuthenticationType) { const config = AwsIotMqttConnectionConfigBuilder.new_mtls_builder_from_path(ProxyConfig.HTTP_PROXY_TLS_CERT_PATH, ProxyConfig.HTTP_PROXY_TLS_KEY_PATH) .with_certificate_authority_from_path(undefined, ProxyConfig.HTTP_PROXY_TLS_ROOT_CA_PATH) .with_clean_session(true) .with_client_id(`node-mqtt-unit-test-${uuid()}`) .with_endpoint(ProxyConfig.HTTP_PROXY_MQTT_ENDPOINT) .with_ping_timeout_ms(5000) .with_http_proxy_options(ProxyConfig.create_http_proxy_options_from_environment(test_type, auth_type)) .build() const client = new MqttClient(undefined); const connection = client.new_connection(config); const promise = new Promise(async (resolve, reject) => { connection.on('connect', async (session_present) => { expect(session_present).toBeFalsy(); const disconnected = connection.disconnect(); await expect(disconnected).resolves.toBeUndefined(); }); connection.on('error', (error) => { reject(error); }) connection.on('disconnect', () => { resolve(true); }) const connected = connection.connect(); await expect(connected).resolves.toBeDefined(); }); await expect(promise).resolves.toBeTruthy(); } conditional_test(is_proxy_environment_enabled())('Proxied Mqtt Connection Tunneling NoAuth', async () => { await test_proxied_mqtt_connection(ProxyTestType.TUNNELING_HTTP, HttpProxyAuthenticationType.None); }); conditional_test(is_proxy_environment_enabled())('Proxied Mqtt Connection Tunneling BasicAuth', async () => { await test_proxied_mqtt_connection(ProxyTestType.TUNNELING_HTTP, HttpProxyAuthenticationType.Basic); }); conditional_test(is_proxy_environment_enabled() && is_tls_to_proxy_enabled())('Proxied Mqtt Connection DoubleTls NoAuth', async () => { await test_proxied_mqtt_connection(ProxyTestType.TUNNELING_DOUBLE_TLS, HttpProxyAuthenticationType.None); }); // Test values copied from aws-c-auth/tests/aws-sig-v4-test-suite/get-vanilla" const DATE_STR = '2015-08-30T12:36:00Z'; const SIGV4TEST_SERVICE = 'service'; const SIGV4TEST_REGION = 'us-east-1'; const SIGV4TEST_METHOD = 'GET'; const SIGV4TEST_PATH = '/'; const SIGV4TEST_UNSIGNED_HEADERS: [string, string][] = [ ['Host', 'example.amazonaws.com'] ]; async function do_body_request_signing(provider: AwsCredentialsProvider) { const signing_config: AwsSigningConfig = { algorithm: AwsSigningAlgorithm.SigV4, signature_type: AwsSignatureType.HttpRequestViaHeaders, provider: provider, region: SIGV4TEST_REGION, service: SIGV4TEST_SERVICE, date: new Date(DATE_STR), signed_body_header: AwsSignedBodyHeaderType.None, }; let stream = new PassThrough(); let body_stream; stream.write("test"); stream.end(() => { body_stream = new InputStream(stream); }); let http_request = new HttpRequest( SIGV4TEST_METHOD, SIGV4TEST_PATH, new HttpHeaders(SIGV4TEST_UNSIGNED_HEADERS), body_stream); return await aws_sign_request(http_request, signing_config); } async function test_x509_credentials(test_type : ProxyTestType, auth_type : HttpProxyAuthenticationType) { const proxy_config = ProxyConfig.create_http_proxy_options_from_environment(test_type, auth_type) let tls_ctx_opt = new TlsContextOptions(); tls_ctx_opt.certificate_filepath = ProxyConfig.HTTP_PROXY_TLS_CERT_PATH; tls_ctx_opt.private_key_filepath = ProxyConfig.HTTP_PROXY_TLS_KEY_PATH; tls_ctx_opt.ca_filepath = ProxyConfig.HTTP_PROXY_TLS_ROOT_CA_PATH; let client_tls_ctx = new ClientTlsContext(tls_ctx_opt); let x509_config : X509CredentialsConfig = { endpoint: ProxyConfig.X509_CREDENTIALS_ENDPOINT, thingName: ProxyConfig.X509_CREDENTIALS_THING_NAME, roleAlias: ProxyConfig.X509_CREDENTIALS_ROLE_ALIAS, tlsContext: client_tls_ctx, httpProxyOptions: proxy_config }; let credentials_provider = AwsCredentialsProvider.newX509(x509_config); const signing_result = await do_body_request_signing(credentials_provider); await expect(signing_result).toBeDefined(); expect(signing_result.method).toBe(SIGV4TEST_METHOD); expect(signing_result.path).toBe(SIGV4TEST_PATH); } conditional_test(is_x509_enabled())('X509 Credentials TLS proxy NoAuth', async () => { await test_x509_credentials(ProxyTestType.TUNNELING_HTTPS, HttpProxyAuthenticationType.None); }); conditional_test(is_x509_enabled())('X509 Credentials double TLS proxy NoAuth', async () => { await test_x509_credentials(ProxyTestType.TUNNELING_DOUBLE_TLS, HttpProxyAuthenticationType.None); }); conditional_test(is_x509_enabled())('X509 Credentials TLS proxy BasicAuth', async () => { await test_x509_credentials(ProxyTestType.TUNNELING_HTTPS, HttpProxyAuthenticationType.Basic); });