diff --git a/documents/MQTT5_Userguide.md b/documents/MQTT5_Userguide.md index f03e888585..0f476dd2d6 100644 --- a/documents/MQTT5_Userguide.md +++ b/documents/MQTT5_Userguide.md @@ -16,7 +16,7 @@ - [MQTT over Websockets with Sigv4 authentication](#mqtt-over-websockets-with-sigv4-authentication) - [Direct MQTT with Custom Authentication](#direct-mqtt-with-custom-authentication) - [MQTT over Websockets with Cognito](#mqtt-over-websockets-with-cognito) - - [HTTP Proxy](#http-proxy) + + [Adding an HTTP Proxy](#adding-an-http-proxy) + [Client Operations](#client-operations) - [Subscribe](#subscribe) - [Unsubscribe](#unsubscribe) @@ -349,7 +349,7 @@ Sigv4-based authentication requires a credentials provider capable of sourcing v -If the default credentials provider chain and AWS region are specified, you do not need to specify any additional configuration, Alternatively, if you're connecting to a special region for which standard pattern matching does not work, or if you need a specific credentials provider, you can specify advanced websocket configuration options. +If the default credentials provider chain and AWS region are specified, you do not need to specify any additional configuration. Alternatively, if you're connecting to a special region for which standard pattern matching does not work, or if you need a specific credentials provider, you can specify advanced websocket configuration options. ```cpp @@ -396,7 +396,7 @@ If your custom authenticator does not use signing, you don't specify anything re ```cpp // Setup custom authorization config Mqtt5CustomAuthConfig customAuth; - customAuth.WithAuthrizaerName(""); + customAuth.WithAuthorizerName(""); customAuth.WithUsername(""); customAuth.WithPassword(); @@ -421,7 +421,7 @@ If your custom authenticator does not use signing, you don't specify anything re ``` -If your custom authorizer uses signing, you must specify the three signed token properties as well. The token signature must be the URI-encoding of the base64 encoding of the digital signature of the token value via the private key associated with the public key that was registered with the custom authorizer. It is your responsibility to URI-encode the token signature. +If your custom authorizer uses signing, you must specify the three signed token properties as well. It is your responsibility to URI-encode the Username, AuthorizerName, and TokenKeyName parameters. ```cpp // Setup custom authorization config @@ -504,7 +504,7 @@ To create a MQTT5 builder configured for this connection, see the following code **Note**: A Cognito identity ID is different from a Cognito identity pool ID and trying to connect with a Cognito identity pool ID will not work. If you are unable to connect, make sure you are passing a Cognito identity ID rather than a Cognito identity pool ID. -### HTTP Proxy +## Adding an HTTP Proxy No matter what your connection transport or authentication method is, you may connect through an HTTP proxy by applying proxy configuration to the builder: diff --git a/samples/README.md b/samples/README.md index c26e1056fd..cc90592e03 100644 --- a/samples/README.md +++ b/samples/README.md @@ -1,9 +1,20 @@ # Sample apps for the AWS IoT Device SDK for C++ v2 -* [Basic Pub-Sub](./pub_sub/basic_pub_sub/README.md) -* [Basic Connect](./mqtt/basic_connect/README.md) +## MQTT5 Samples +#### MQTT5 is the recommended MQTT Client. It has many benefits over MQTT311 outlined in the [MQTT5 User Guide](../documents/MQTT5_Userguide.md) * [Mqtt5 Pub-Sub](./mqtt5/mqtt5_pubsub/README.md) + + [Direct MQTT with X509-based mutual TLS](./mqtt5/mqtt5_pubsub/README.md#direct-mqtt-with-x509-based-mutual-tls) + + [MQTT over Websockets with Sigv4 authentication](./mqtt5/mqtt5_pubsub/README.md#mqtt-over-websockets-with-sigv4-authentication) + + [Direct MQTT with Custom Authentication](./mqtt5/mqtt5_pubsub/README.md#direct-mqtt-with-custom-authentication) + + [MQTT over Websockets with Cognito](./mqtt5/mqtt5_pubsub/README.md#mqtt-over-websockets-with-cognito) + + [HTTP Proxy](./mqtt5/mqtt5_pubsub/README.md#http-proxy) * [Mqtt5 Shared Subscription](./mqtt5/mqtt5_shared_subscription/README.md) +* [Mqtt5 Jobs](./jobs/mqtt5_job_execution/README.md) +* [Mqtt5 Shadow](./shadow/mqtt5_shadow_sync/README.md) +* [Mqtt5 Fleet Provisioning](./fleet_provisioning/mqtt5_fleet_provisioning/README.md) +## MQTT311 Samples +* [Basic Pub-Sub](./pub_sub/basic_pub_sub/README.md) +* [Basic Connect](./mqtt/basic_connect/README.md) * [Websocket Connect](./mqtt/websocket_connect/README.md) * [PKCS#11 Connect](./mqtt/pkcs11_connect/README.md) * [PKCS#12 Connect](./mqtt/pkcs12_connect/README.md) @@ -11,17 +22,17 @@ * [Windows Certificate MQTT Connect](./mqtt/windows_cert_connect/README.md) * [Custom Authorizer Connect](./mqtt/custom_authorizer_connect/README.md) * [Cognito Connect](./mqtt/cognito_connect/README.md) -* [Secure Tunnel](./secure_tunneling/secure_tunnel/README.md) -* [Secure Tunnel Notification](./secure_tunneling/tunnel_notification/README.md) * [Shadow](./shadow/shadow_sync/README.md) * [Jobs](./jobs/job_execution/README.md) -* [Mqtt5 Jobs](./jobs/mqtt5_job_execution/README.md) * [Fleet provisioning](./fleet_provisioning/fleet_provisioning/README.md) +## Other Samples +* [Secure Tunnel](./secure_tunneling/secure_tunnel/README.md) +* [Secure Tunnel Notification](./secure_tunneling/tunnel_notification/README.md) +* [Cycle Pub-Sub](./pub_sub/cycle_pub_sub/README.md) * [Greengrass discovery](./greengrass/basic_discovery/README.md) * [Greengrass IPC](./greengrass/ipc/README.md) -* [Device Defender](./device_defender/basic_report/README.md) * [Mqtt5 Device Defender](./device_defender/mqtt5_basic_report/README.md) -* [Cycle Pub-Sub](./pub_sub/cycle_pub_sub/README.md) +* [Mqtt311 Device Defender](./device_defender/basic_report/README.md) ## Build Instruction @@ -54,13 +65,13 @@ cmake -B build -S . -DCMAKE_PREFIX_PATH="" cmake --build build --config "" ``` -This will compile all the samples at once and place the executables under the `build` directory relative to their file path. To view the commands for a given sample, run the compiled program and pass `--help`. For example, with the PubSub sample: +This will compile all the samples at once and place the executables under the `build` directory relative to their file path. To view the commands for a given sample, run the compiled program and pass `--help`. For example, with the MQTT5 PubSub sample: ```sh -./build/pub_sub/basic_pub_sub/basic-pub-sub --help +./build/mqtt5/mqtt5_pubsub/mqtt5_pubsub --help ``` -This will compile all of the samples at once. You can then find the samples in the `aws-iot-device-sdk-cpp-v2/samples/build` folder. For example, the PubSub sample will be located at `aws-iot-device-sdk-cpp-v2/samples/build/pubsub/basic_pubsub`. +This will compile all of the samples at once. You can then find the samples in the `aws-iot-device-sdk-cpp-v2/samples/build` folder. For example, the MQTT5 PubSub sample will be located at `aws-iot-device-sdk-cpp-v2/samples/build/mqtt5/mqtt5_pubsub`. For CMake versions that do not support the `-B` command, go to the `aws-iot-device-sdk-cpp-v2/samples` directory and run the following commands: @@ -84,7 +95,7 @@ Note that building all the samples at once is currently only available in the V2 All samples will show their options by passing in `--help`. For example: ```sh -./build/basic-pub-sub --help +./build/mqtt5/mqtt5_pubsub/mqtt5_pubsub --help ``` Which will result in output showing all of the options that can be passed in at the command line, along with descriptions of what each does and whether or not they are optional or not. diff --git a/samples/mqtt5/mqtt5_pubsub/README.md b/samples/mqtt5/mqtt5_pubsub/README.md index aa3436b30a..f89e7ac317 100644 --- a/samples/mqtt5/mqtt5_pubsub/README.md +++ b/samples/mqtt5/mqtt5_pubsub/README.md @@ -69,3 +69,238 @@ You can also pass a Certificate Authority file (CA) if your certificate and key ``` sh ./mqtt5_pubsub --endpoint --cert --key --topic --ca_file ``` +## Alternate Connection Configuration Methods supported by AWS IoT Core +Alternate connection configuration methods can be set using the Mqtt5ClientBuilder class. We strongly recommend using the Mqtt5ClientBuilder class to configure MQTT5 clients when connecting to AWS IoT Core. The builder simplifies configuration for all authentication methods supported by AWS IoT Core. + +This section shows samples for all of the authentication possibilities. + +### Authentication Methods +* [Direct MQTT with X509-based mutual TLS](#direct-mqtt-with-x509-based-mutual-tls) +* [MQTT over Websockets with Sigv4 authentication](#mqtt-over-websockets-with-sigv4-authentication) +* [Direct MQTT with Custom Authentication](#direct-mqtt-with-custom-authentication) +* [MQTT over Websockets with Cognito](#mqtt-over-websockets-with-cognito) +### HTTP Proxy +* [Adding an HTTP Proxy](#adding-an-http-proxy) + +### Direct MQTT with X509-based mutual TLS + +For X509 based mutual TLS, you can create a client where the certificate and private key are configured by path: + +```cpp + // Create a Client using Mqtt5ClientBuilder + Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithMtlsFromPath( + "", "", ""); + + /* You can setup other client options and lifecycle event callbacks before call builder->Build(). + ** Once the the client get built, you could no longer update the client options or connection options + ** on the created client. + */ + + // Build Mqtt5Client + std::shared_ptr mqtt5Client = builder->Build(); + + if (mqtt5Client == nullptr) + { + fprintf(stdout, "Client creation failed.\n"); + return -1; + } + + // start use the mqtt5 client + +``` + + + +### MQTT over Websockets with Sigv4 authentication + +Sigv4-based authentication requires a credentials provider capable of sourcing valid AWS credentials. Sourced credentials will sign the websocket upgrade request made by the client while connecting. The default credentials provider chain supported by the SDK is capable of resolving credentials in a variety of environments according to a chain of priorities: + + +```Environment -> Profile (local file system) -> STS Web Identity -> IMDS (ec2) or ECS``` + + + +If the default credentials provider chain and AWS region are specified, you do not need to specify any additional configuration. Alternatively, if you're connecting to a special region for which standard pattern matching does not work, or if you need a specific credentials provider, you can specify advanced websocket configuration options. + + +```cpp + // Create websocket configuration + Aws::Crt::Auth::CredentialsProviderChainDefaultConfig defaultConfig; + std::shared_ptr provider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderChainDefault(defaultConfig); + if (!provider) + { + fprintf(stderr, "Failure to create credentials provider!\n"); + exit(-1); + } + Aws::Iot::WebsocketConfig websocketConfig(, provider); + + // Create a Client using Mqtt5ClientBuilder + Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithWebsocket( + "", websocketConfig); + + /* You can setup other client options and lifecycle event callbacks before call builder->Build(). + ** Once the the client get built, you could no longer update the client options or connection options + ** on the created client. + */ + + // Build Mqtt5Client + std::shared_ptr mqtt5Client = builder->Build(); + + if (mqtt5Client == nullptr) + { + fprintf(stdout, "Client creation failed.\n"); + return -1; + } + + +``` + + +### Direct MQTT with Custom Authentication + +AWS IoT Core Custom Authentication allows you to use a lambda to gate access to IoT Core resources. For this authentication method,you must supply an additional configuration structure containing fields relevant to AWS IoT Core Custom Authentication. + + + +If your custom authenticator does not use signing, you don't specify anything related to the token signature: + +```cpp + // Setup custom authorization config + Mqtt5CustomAuthConfig customAuth; + customAuth.WithAuthorizerName(""); + customAuth.WithUsername(""); + customAuth.WithPassword(); + + // Create a Client using Mqtt5ClientBuilder + Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithCustomCustomAuthorizer( + "", customAuth); + + /* You can setup other client options and lifecycle event callbacks before call builder->Build(). + ** Once the the client get built, you could no longer update the client options or connection options + ** on the created client. + */ + + // Build Mqtt5Client + std::shared_ptr mqtt5Client = builder->Build(); + + if (mqtt5Client == nullptr) + { + fprintf(stdout, "Client creation failed.\n"); + return -1; + } + +``` + + +If your custom authorizer uses signing, you must specify the three signed token properties as well. It is your responsibility to URI-encode the Username, AuthorizerName, and TokenKeyName parameters. + +```cpp + // Setup custom authorization config + Mqtt5CustomAuthConfig customAuth; + customAuth.WithAuthrizaerName(""); + customAuth.WithUsername(""); + customAuth.WithPassword(); + customAuth.WithTokenSignature("") + + // Create a Client using Mqtt5ClientBuilder + Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithCustomCustomAuthorizer( + "", customAuth); + + /* You can setup other client options and lifecycle event callbacks before call builder->Build(). + ** Once the the client get built, you could no longer update the client options or connection options + ** on the created client. + */ + + // Build Mqtt5Client + std::shared_ptr mqtt5Client = builder->Build(); + + if (mqtt5Client == nullptr) + { + fprintf(stdout, "Client creation failed.\n"); + return -1; + } + +``` + +In both cases, the builder will construct a final CONNECT packet username field value for you based on the values configured. Do not add the token-signing fields to the value of the username that you assign within the custom authentication config structure. Similarly, do not add any custom authentication related values to the username in the CONNECT configuration optionally attached to the client configuration. The builder will do everything for you. + + +### MQTT over Websockets with Cognito + +A MQTT5 websocket connection can be made using Cognito to authenticate rather than the AWS credentials located on the device or via key and certificate. Instead, Cognito can authenticate the connection using a valid Cognito identity ID. This requires a valid Cognito identity ID, which can be retrieved from a Cognito identity pool. A Cognito identity pool can be created from the AWS console. + +To create a MQTT5 builder configured for this connection, see the following code: + +```cpp + // Create websocket configuration + Aws::Crt::Auth::CredentialsProviderChainDefaultConfig defaultConfig; + std::shared_ptr provider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderChainDefault(defaultConfig); + + Aws::Crt::Auth::CredentialsProviderCognitoConfig cognitoConfig; + // See https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html for Cognito endpoints + cognitoConfig.Endpoint = "cognito-identity..amazonaws.com"; + cognitoConfig.Identity = ""; + Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitDefaultClient(); + cognitoConfig.TlsCtx = Aws::Crt::Io::TlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT); + std::shared_ptr provider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderCognito(cognitoConfig); + + if (!provider) + { + fprintf(stderr, "Failure to create credentials provider!\n"); + exit(-1); + } + Aws::Iot::WebsocketConfig websocketConfig(, provider); + + // Create a Client using Mqtt5ClientBuilder + Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithWebsocket( + "", websocketConfig); + + /* You can setup other client options and lifecycle event callbacks before call builder->Build(). + ** Once the the client get built, you could no longer update the client options or connection options + ** on the created client. + */ + + // Build Mqtt5Client + std::shared_ptr mqtt5Client = builder->Build(); + + if (mqtt5Client == nullptr) + { + fprintf(stdout, "Client creation failed.\n"); + return -1; + } + + +``` + +**Note**: A Cognito identity ID is different from a Cognito identity pool ID and trying to connect with a Cognito identity pool ID will not work. If you are unable to connect, make sure you are passing a Cognito identity ID rather than a Cognito identity pool ID. + +## Adding an HTTP Proxy + +No matter what your connection transport or authentication method is, you may connect through an HTTP proxy by applying proxy configuration to the builder: + +```cpp + // Create a Client using Mqtt5ClientBuilder + Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithXXXXX( ... ); + + Http::HttpClientConnectionProxyOptions proxyOptions; + proxyOptions.HostName = ""; + proxyOptions.Port = ; + builder->WithHttpProxyOptions(proxyOptions); + + /* You can setup other client options and lifecycle event callbacks before call builder->Build(). + ** Once the the client get built, you could no longer update the client options or connection options + ** on the created client. + */ + + // Build Mqtt5Client + std::shared_ptr mqtt5Client = builder->Build(); + + if (mqtt5Client == nullptr) + { + fprintf(stdout, "Client creation failed.\n"); + return -1; + } + +``` + +SDK Proxy support also includes support for basic authentication and TLS-to-proxy. SDK proxy support does not include any additional proxy authentication methods (kerberos, NTLM, etc...) nor does it include non-HTTP proxies (SOCKS5, for example). \ No newline at end of file