Skip to content

Commit

Permalink
Merge branch 'main' into migration_guide
Browse files Browse the repository at this point in the history
  • Loading branch information
alfred2g authored Feb 2, 2024
2 parents e391c16 + 14af725 commit 48427dd
Show file tree
Hide file tree
Showing 3 changed files with 262 additions and 16 deletions.
10 changes: 5 additions & 5 deletions documents/MQTT5_Userguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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("<Name of your custom authorizer>");
customAuth.WithAuthorizerName("<Name of your custom authorizer>");
customAuth.WithUsername("<Value of the username field that should be passed to the authorizer's lambda>");
customAuth.WithPassword(<Binary data value of the password field to be passed to the authorizer lambda>);
Expand All @@ -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
Expand Down Expand Up @@ -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:

Expand Down
33 changes: 22 additions & 11 deletions samples/README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
# 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)
* [x509 Credentials Provider Connect](./mqtt/x509_credentials_provider_connect/README.md)
* [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

Expand Down Expand Up @@ -54,13 +65,13 @@ cmake -B build -S . -DCMAKE_PREFIX_PATH="<absolute path sdk-cpp-workspace dir>"
cmake --build build --config "<Release|RelWithDebInfo|Debug>"
```

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:

Expand All @@ -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.
Expand Down
235 changes: 235 additions & 0 deletions samples/mqtt5/mqtt5_pubsub/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,238 @@ You can also pass a Certificate Authority file (CA) if your certificate and key
``` sh
./mqtt5_pubsub --endpoint <endpoint> --cert <path to the certificate> --key <path to the private key> --topic <topic name> --ca_file <path to root CA>
```
## 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(
"<clientEndpoint>", "<certificateFilePath>", "<privateKeyFilePath>");

/* 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<Aws::Crt::Mqtt5Client> 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<Aws::Crt::Auth::ICredentialsProvider> provider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderChainDefault(defaultConfig);
if (!provider)
{
fprintf(stderr, "Failure to create credentials provider!\n");
exit(-1);
}
Aws::Iot::WebsocketConfig websocketConfig(<signing region>, provider);
// Create a Client using Mqtt5ClientBuilder
Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithWebsocket(
"<clientEndpoint>", 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<Aws::Crt::Mqtt5Client> 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("<Name of your custom authorizer>");
customAuth.WithUsername("<Value of the username field that should be passed to the authorizer's lambda>");
customAuth.WithPassword(<Binary data value of the password field to be passed to the authorizer lambda>);

// Create a Client using Mqtt5ClientBuilder
Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithCustomCustomAuthorizer(
"<clientEndpoint>", 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<Aws::Crt::Mqtt5Client> 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("<Name of your custom authorizer>");
customAuth.WithUsername("<Value of the username field that should be passed to the authorizer's lambda>");
customAuth.WithPassword(<Binary data value of the password field to be passed to the authorizer lambda>);
customAuth.WithTokenSignature("<The signature of the custom authorizer>")
// Create a Client using Mqtt5ClientBuilder
Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithCustomCustomAuthorizer(
"<clientEndpoint>", 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<Aws::Crt::Mqtt5Client> 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<Aws::Crt::Auth::ICredentialsProvider> 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.<region>.amazonaws.com";
cognitoConfig.Identity = "<Cognito Identity ID>";
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<Aws::Crt::Auth::ICredentialsProvider> provider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderCognito(cognitoConfig);

if (!provider)
{
fprintf(stderr, "Failure to create credentials provider!\n");
exit(-1);
}
Aws::Iot::WebsocketConfig websocketConfig(<signing region>, provider);

// Create a Client using Mqtt5ClientBuilder
Aws::Iot::Mqtt5ClientBuilder *builder = Aws::Iot::Mqtt5ClientBuilder::NewMqtt5ClientBuilderWithWebsocket(
"<clientEndpoint>", 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<Aws::Crt::Mqtt5Client> 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 = "<proxyHost>";
proxyOptions.Port = <proxyPort>;
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<Aws::Crt::Mqtt5Client> 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).

0 comments on commit 48427dd

Please sign in to comment.