diff --git a/samples/README.md b/samples/README.md index f9457ac56..c7fe6f4d4 100644 --- a/samples/README.md +++ b/samples/README.md @@ -5,6 +5,10 @@ * [Mqtt5 Pub-Sub](./mqtt5/mqtt5_pubsub/README.md) * [Mqtt5 Shared Subscription](./mqtt5/mqtt5_shared_subscription/README.md) * [Websocket Connect](./mqtt/websocket_connect/README.md) +* [Websocket Connect/custom auth](./mqtt/websocket_connect/README_custom_auth.md) +* [Websocket Connect/username and password](./mqtt/websocket_connect/README_username_password.md) +* [Websocket Connect/proxy](./mqtt/websocket_connect/README_proxy.md) +* [Websocket Connect/static credentials](./mqtt/websocket_connect/README_static_credentials.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) diff --git a/samples/mqtt/websocket_connect/README.md b/samples/mqtt/websocket_connect/README.md index 1e3237b6e..74657daf7 100644 --- a/samples/mqtt/websocket_connect/README.md +++ b/samples/mqtt/websocket_connect/README.md @@ -2,7 +2,16 @@ [**Return to main sample list**](../../README.md) -This sample makes an MQTT connection via Websockets and then disconnects. On startup, the device connects to the server via Websockets and then disconnects right after. This sample is for reference on connecting via Websockets. This sample demonstrates the most straightforward way to connect via Websockets by querying the AWS credentials for the connection from the device's environment variables or local files. +This sample makes an MQTT connection via Websockets and then disconnects. +On startup, the device connects to the server via Websockets and then disconnects right after. +This sample is for reference on connecting via Websockets. +This sample demonstrates the most straightforward way to connect via Websockets by querying the AWS credentials for the connection from the device's environment variables or local files. + +If you want to use custom auth (or static creds, or basic auth, etc) instead, +then you will need to replace part of the sample (connection\_setup function) with a code snippet we provided in its corresponding readme. + +* [Websocket Connect/custom auth](./README_custom_auth.md) +* [Websocket Connect/static credentials](./README_static_credentials.md) Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. @@ -37,7 +46,13 @@ For this sample, using Websockets will attempt to fetch the AWS credentials to a ## How to run -To run the websocket connect use the following command: +To use a proxy server which is optional pass the following arguments + +Optional parameters: +``` +--proxy_host +--proxy_port +``` ``` sh ./websocket-connect --endpoint --signing_region diff --git a/samples/mqtt/websocket_connect/README_custom_auth.md b/samples/mqtt/websocket_connect/README_custom_auth.md new file mode 100644 index 000000000..ae3240fbc --- /dev/null +++ b/samples/mqtt/websocket_connect/README_custom_auth.md @@ -0,0 +1,96 @@ +# Websocket Connect with Custom Authentication + +[**Return to main sample list**](../../README.md) + +This sample makes an MQTT connection and connects through a [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html). +On startup, the device connects to the server and then disconnects. +This sample is for reference on connecting using a Custom Authorizer. +Using a Custom Authorizer allows you to perform your own authorization using an AWS Lambda function. +See [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html) for more information. +You will need to setup your Custom Authorizer so that the lambda function returns a policy document. +See [this page on the documentation](https://docs.aws.amazon.com/iot/latest/developerguide/config-custom-auth.html) for more details and example return result. +You can customize this lambda function as needed for your application to provide your own security measures based on the needs of your application. +Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. +Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. + +If you want to use simple or custom auth (or static creds, or basic auth, etc) instead, +then you will need to replace part of the sample (connection\_setup function) with a code snippet we provided in its corresponding readme. + +Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. + +
+(see sample policy) +
+{
+  "Version": "2012-10-17",
+  "Statement": [
+    {
+      "Effect": "Allow",
+      "Action": [
+        "iot:Connect"
+      ],
+      "Resource": [
+        "arn:aws:iot:region:account:client/test-*"
+      ]
+    }
+  ]
+}
+
+ + +Replace with the following with the data from your AWS account: +* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. +* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. + +Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. + +For this sample, using Websockets will attempt to connect using custom auth. + +
+ +
+ (code snipet to replace similar section) +
+
+void connection_setup(int argc, char \*argv[], ApiHandle &apiHandle, Utils::cmdData &cmdData,
+    Aws::Iot::MqttClientConnectionConfigBuilder &clientConfigBuilder)
+{
+  cmdData = Utils::parseSampleInputCustomAuthorizerConnect(argc, argv, &apiHandle);
+  // Create the MQTT builder and populate it with data from cmdData.
+  Aws::Crt::Auth::CredentialsProviderChainDefaultConfig defaultConfig;
+  std::shared_ptr provider =
+      Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderChainDefault(defaultConfig);
+  Aws::Iot::WebsocketConfig websocketConfig((cmdData.input_signingRegion), provider);
+  clientConfigBuilder = Aws::Iot::MqttClientConnectionConfigBuilder(websocketConfig);
+  clientConfigBuilder.WithEndpoint((cmdData.input_endpoint));
+  clientConfigBuilder.WithCustomAuthorizer(
+      (cmdData.input_customAuthUsername),
+      (cmdData.input_customAuthorizerName),
+      (cmdData.input_customAuthorizerSignature),
+      (cmdData.input_customAuthPassword),
+      (cmdData.input_customTokenKeyName),
+      (cmdData.input_customTokenValue));
+}
+
+
+
+
+ +## How to run + +Options for custom auth +``` +--custom_auth_username +--custom_auth_authorizer_name +--custom_auth_authorizer_signature +--custom_auth_password +--custom_auth_token_name +--custom_auth_token_value +``` + +To run the websocket connect use the following command: + +``` +./websocket-connect --endpoint --signing_region --custom_auth_username --custom_auth_authorizer_name --custom_auth_authorizer_signature --custom_auth_password --custom_auth_token_name --custom_auth_token_value +``` + diff --git a/samples/mqtt/websocket_connect/README_static_credentials.md b/samples/mqtt/websocket_connect/README_static_credentials.md new file mode 100644 index 000000000..b2101a2d8 --- /dev/null +++ b/samples/mqtt/websocket_connect/README_static_credentials.md @@ -0,0 +1,81 @@ +# Websocket Connect with static credentials + +[**Return to main sample list**](../../README.md) + +This sample makes an MQTT connection via Websockets and then disconnects. +On startup, the device connects to the server via Websockets then disconnects right after. +This sample demonstrates connecting via static credentials. + +If you want to use simple or custom auth (or static creds, or basic auth, etc) instead, +then you will need to replace part of the sample (connection\_setup function) with a code snippet we provided in its corresponding readme. + +Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. + +
+(see sample policy) +
+{
+  "Version": "2012-10-17",
+  "Statement": [
+    {
+      "Effect": "Allow",
+      "Action": [
+        "iot:Connect"
+      ],
+      "Resource": [
+        "arn:aws:iot:region:account:client/test-*"
+      ]
+    }
+  ]
+}
+
+ +Replace with the following with the data from your AWS account: +* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. +* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. + +Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. + +For this sample, using Websockets will attempt to fetch the AWS credentials to authorize the connection from static credentials. + +
+ + +
+ (code snipet to replace similar section) +
+
+void connection_setup(int argc, char \*argv[], ApiHandle &apiHandle, Utils::cmdData &cmdData,
+    Aws::Iot::MqttClientConnectionConfigBuilder &clientConfigBuilder)
+{
+    cmdData = Utils::parseSampleInputWebsocketStaticCredentialsConnect(argc, argv, &apiHandle);
+    Aws::Crt::Auth::CredentialsProviderChainDefaultConfig defaultConfig;
+    std::shared_ptr provider = nullptr;
+    Aws::Crt::Auth::CredentialsProviderStaticConfig providerConfig;
+    providerConfig.AccessKeyId = aws_byte_cursor_from_c_str((cmdData.input_accessKeyId.c_str()));
+    providerConfig.SecretAccessKey = aws_byte_cursor_from_c_str((cmdData.input_secretAccessKey.c_str()));
+    providerConfig.SessionToken = aws_byte_cursor_from_c_str((cmdData.input_sessionToken.c_str()));
+    provider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderStatic(providerConfig);
+    Aws::Iot::WebsocketConfig config(cmdData.input_signingRegion, provider);
+    clientConfigBuilder = Aws::Iot::MqttClientConnectionConfigBuilder(config);
+    clientConfigBuilder.WithEndpoint((cmdData.input_endpoint));
+}
+
+
+
+ +## How to run + +Options for static credentials +``` +--access_key_id +--secret_access_key +--session_token +``` + +To run the websocket connect use the following command: + +``` sh +./websocket-connect --endpoint --signing_region --access_key_id --secret_access_key --session_token +``` + diff --git a/samples/mqtt/websocket_connect/main.cpp b/samples/mqtt/websocket_connect/main.cpp index 45cb92e44..cf6ce8480 100644 --- a/samples/mqtt/websocket_connect/main.cpp +++ b/samples/mqtt/websocket_connect/main.cpp @@ -17,23 +17,15 @@ using namespace Aws::Crt; -int main(int argc, char *argv[]) +void connection_setup( + int argc, + char *argv[], + ApiHandle &apiHandle, + Utils::cmdData &cmdData, + Aws::Iot::MqttClientConnectionConfigBuilder &clientConfigBuilder) { - /************************ Setup ****************************/ - - // Do the global initialization for the API. - ApiHandle apiHandle; - - /** - * cmdData is the arguments/input from the command line placed into a single struct for - * use in this sample. This handles all of the command line parsing, validating, etc. - * See the Utils/CommandLineUtils for more information. - */ - Utils::cmdData cmdData = Utils::parseSampleInputWebsocketConnect(argc, argv, &apiHandle); + cmdData = Utils::parseSampleInputWebsocketConnect(argc, argv, &apiHandle); - // Create the MQTT builder and populate it with data from cmdData. - Aws::Iot::MqttClient client; - Aws::Iot::MqttClientConnectionConfigBuilder clientConfigBuilder; std::shared_ptr provider = nullptr; Aws::Crt::Auth::CredentialsProviderChainDefaultConfig defaultConfig; provider = Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderChainDefault(defaultConfig); @@ -61,6 +53,25 @@ int main(int argc, char *argv[]) clientConfigBuilder.WithPortOverride(static_cast(cmdData.input_port)); } clientConfigBuilder.WithEndpoint(cmdData.input_endpoint); +} + +int main(int argc, char *argv[]) +{ + /************************ Setup ****************************/ + + // Do the global initialization for the API. + ApiHandle apiHandle; + /** + * cmdData is the arguments/input from the command line placed into a single struct for + * use in this sample. This handles all of the command line parsing, validating, etc. + * See the Utils/CommandLineUtils for more information. + */ + Utils::cmdData cmdData; + Aws::Iot::MqttClient client; + // Create the MQTT builder and populate it with data from cmdData. + Aws::Iot::MqttClientConnectionConfigBuilder clientConfigBuilder; + + connection_setup(argc, argv, apiHandle, cmdData, clientConfigBuilder); // Create the MQTT connection from the MQTT builder auto clientConfig = clientConfigBuilder.Build(); diff --git a/samples/utils/CommandLineUtils.cpp b/samples/utils/CommandLineUtils.cpp index 40e08b79a..3ef7b090e 100644 --- a/samples/utils/CommandLineUtils.cpp +++ b/samples/utils/CommandLineUtils.cpp @@ -21,6 +21,9 @@ namespace Utils static const char *m_cmd_proxy_host = "proxy_host"; static const char *m_cmd_proxy_port = "proxy_port"; static const char *m_cmd_signing_region = "signing_region"; + static const char *m_cmd_access_key_id = "access_key_id"; + static const char *m_cmd_secret_access_key = "secret_access_key"; + static const char *m_cmd_session_token = "session_token"; static const char *m_cmd_x509_endpoint = "x509_endpoint"; static const char *m_cmd_x509_role = "x509_role_alias"; static const char *m_cmd_x509_thing_name = "x509_thing_name"; @@ -40,6 +43,8 @@ namespace Utils static const char *m_cmd_custom_auth_authorizer_name = "custom_auth_authorizer_name"; static const char *m_cmd_custom_auth_authorizer_signature = "custom_auth_authorizer_signature"; static const char *m_cmd_custom_auth_password = "custom_auth_password"; + static const char *m_cmd_custom_auth_token_name = "custom_auth_token_name"; + static const char *m_cmd_custom_token_value = "custom_auth_token_value"; static const char *m_cmd_verbosity = "verbosity"; static const char *m_cmd_log_file = "log_file"; static const char *m_cmd_cognito_identity = "cognito_identity"; @@ -601,6 +606,9 @@ namespace Utils cmdUtils.AddCommonMQTTCommands(); cmdUtils.AddCommonCustomAuthorizerCommands(); cmdUtils.RegisterCommand(m_cmd_client_id, "", "Client id to use (optional, default='test-*')"); + cmdUtils.RegisterCommand(m_cmd_custom_auth_password, "", "Password (optional)"); + cmdUtils.RegisterCommand(m_cmd_custom_auth_token_name, "", "Token name (optional)"); + cmdUtils.RegisterCommand(m_cmd_custom_token_value, "", "Token value (optional)"); cmdUtils.RemoveCommand("ca_file"); s_addLoggingSendArgumentsStartLogging(argc, argv, api_handle, &cmdUtils); cmdData returnData = cmdData(); @@ -612,6 +620,9 @@ namespace Utils returnData.input_customAuthorizerSignature = cmdUtils.GetCommandOrDefault(m_cmd_custom_auth_authorizer_signature, ""); returnData.input_customAuthPassword = cmdUtils.GetCommandOrDefault(m_cmd_custom_auth_password, ""); + returnData.input_customTokenKeyName = cmdUtils.GetCommandOrDefault(m_cmd_custom_auth_token_name, ""); + returnData.input_customTokenValue = cmdUtils.GetCommandOrDefault(m_cmd_custom_token_value, ""); + return returnData; } @@ -651,6 +662,39 @@ namespace Utils } return returnData; } + cmdData parseSampleInputWebsocketStaticCredentialsConnect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle) + { + CommandLineUtils cmdUtils = CommandLineUtils(); + cmdUtils.RegisterProgramName("websocket-connect"); + cmdUtils.AddCommonMQTTCommands(); + cmdUtils.AddCommonProxyCommands(); + cmdUtils.RegisterCommand(m_cmd_signing_region, "", "The signing region used for the websocket signer"); + cmdUtils.RegisterCommand(m_cmd_client_id, "", "Client id to use (optional, default='test-*')"); + cmdUtils.RegisterCommand(m_cmd_port_override, "", "The port override to use when connecting (optional)"); + cmdUtils.RegisterCommand(m_cmd_access_key_id, "", "The Access key ID (optional)"); + cmdUtils.RegisterCommand(m_cmd_secret_access_key, "", "The secret access key (optional)"); + cmdUtils.RegisterCommand(m_cmd_session_token, "", "The session token (optional)"); + s_addLoggingSendArgumentsStartLogging(argc, argv, api_handle, &cmdUtils); + + cmdData returnData = cmdData(); + s_parseCommonMQTTCommands(&cmdUtils, &returnData); + returnData.input_clientId = + cmdUtils.GetCommandOrDefault(m_cmd_client_id, Aws::Crt::String("test-") + Aws::Crt::UUID().ToString()); + returnData.input_signingRegion = cmdUtils.GetCommandRequired(m_cmd_signing_region, m_cmd_region); + if (cmdUtils.HasCommand(m_cmd_proxy_host)) + { + returnData.input_proxyHost = cmdUtils.GetCommandRequired(m_cmd_proxy_host); + returnData.input_proxyPort = atoi(cmdUtils.GetCommandOrDefault(m_cmd_proxy_port, "8080").c_str()); + } + if (cmdUtils.HasCommand(m_cmd_port_override)) + { + returnData.input_port = atoi(cmdUtils.GetCommandOrDefault(m_cmd_port_override, "0").c_str()); + } + returnData.input_accessKeyId = cmdUtils.GetCommandRequired(m_cmd_access_key_id, ""); + returnData.input_secretAccessKey = cmdUtils.GetCommandRequired(m_cmd_secret_access_key, ""); + returnData.input_sessionToken = cmdUtils.GetCommandRequired(m_cmd_session_token, ""); + return returnData; + } cmdData parseSampleInputWebsocketConnect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle) { @@ -661,6 +705,9 @@ namespace Utils cmdUtils.RegisterCommand(m_cmd_signing_region, "", "The signing region used for the websocket signer"); cmdUtils.RegisterCommand(m_cmd_client_id, "", "Client id to use (optional, default='test-*')"); cmdUtils.RegisterCommand(m_cmd_port_override, "", "The port override to use when connecting (optional)"); + cmdUtils.RegisterCommand(m_cmd_access_key_id, "", "The Access key ID (optional)"); + cmdUtils.RegisterCommand(m_cmd_secret_access_key, "", "The secret access key (optional)"); + cmdUtils.RegisterCommand(m_cmd_session_token, "", "The session token (optional)"); s_addLoggingSendArgumentsStartLogging(argc, argv, api_handle, &cmdUtils); cmdData returnData = cmdData(); diff --git a/samples/utils/CommandLineUtils.h b/samples/utils/CommandLineUtils.h index 16c7b2db0..13123ba40 100644 --- a/samples/utils/CommandLineUtils.h +++ b/samples/utils/CommandLineUtils.h @@ -220,6 +220,10 @@ namespace Utils uint64_t input_count; // Websockets Aws::Crt::String input_signingRegion; + + Aws::Crt::String input_accessKeyId; + Aws::Crt::String input_secretAccessKey; + Aws::Crt::String input_sessionToken; // Cognito Aws::Crt::String input_cognitoIdentity; Aws::Crt::String input_cognitoEndpoint; @@ -228,6 +232,8 @@ namespace Utils Aws::Crt::String input_customAuthorizerName; Aws::Crt::String input_customAuthorizerSignature; Aws::Crt::String input_customAuthPassword; + Aws::Crt::String input_customTokenKeyName; + Aws::Crt::String input_customTokenValue; // Fleet provisioning Aws::Crt::String input_templateName; Aws::Crt::String input_templateParameters; @@ -290,6 +296,7 @@ namespace Utils cmdData parseSampleInputCognitoConnect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle); cmdData parseSampleInputCustomAuthorizerConnect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle); cmdData parseSampleInputPKCS11Connect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle); + cmdData parseSampleInputWebsocketStaticCredentialsConnect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle); cmdData parseSampleInputWebsocketConnect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle); cmdData parseSampleInputWindowsCertificateConnect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle); cmdData parseSampleInputX509Connect(int argc, char *argv[], Aws::Crt::ApiHandle *api_handle);