Skip to content

Commit bca2450

Browse files
Added custom authorizer sample (#423)
Adds a new custom authorizer sample and support to the V2 C++ SDK * Added custom authorizer sample * Clang format fix * Update to use correct function naming * More clang-format fixes * Modified Codebuild custom authorizer name with better name * Added custom authorizer sample to README * Updated to use latest CRT release
1 parent 7ff4354 commit bca2450

File tree

9 files changed

+195
-2
lines changed

9 files changed

+195
-2
lines changed

.builder/actions/build_samples.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def run(self, env):
2020
'samples/mqtt/websocket_connect',
2121
'samples/mqtt/x509_credentials_provider_connect',
2222
'samples/mqtt/windows_cert_connect',
23+
'samples/mqtt/custom_authorizer_connect',
2324
'samples/shadow/shadow_sync',
2425
'samples/greengrass/basic_discovery',
2526
'samples/identity/fleet_provisioning',
@@ -52,7 +53,7 @@ def run(self, env):
5253
steps.append(['cmake',
5354
'--build', build_path,
5455
'--config', 'RelWithDebInfo'])
55-
56+
5657
for sample_path in da_samples:
5758
build_path = os.path.join('build', sample_path)
5859
steps.append(['cmake',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
env
6+
7+
pushd $CODEBUILD_SRC_DIR/samples/mqtt/custom_authorizer_connect
8+
9+
mkdir _build
10+
cd _build
11+
cmake -DCMAKE_PREFIX_PATH=/tmp/install ..
12+
make -j
13+
14+
ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "unit-test/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')
15+
AUTH_NAME=$(aws secretsmanager get-secret-value --secret-id "unit-test/authorizer-name" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')
16+
AUTH_PASSWORD=$(aws secretsmanager get-secret-value --secret-id "unit-test/authorizer-password" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')
17+
18+
echo "Custom authorizer connect test"
19+
./custom-authorizer-connect --endpoint $ENDPOINT --custom_auth_authorizer_name $AUTH_NAME --custom_auth_password $AUTH_PASSWORD
20+
21+
popd

codebuild/samples/linux-smoke-tests.yml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ phases:
1919
- $CODEBUILD_SRC_DIR/codebuild/samples/connect-websocket-linux.sh
2020
- $CODEBUILD_SRC_DIR/codebuild/samples/pkcs11-connect-linux.sh
2121
- $CODEBUILD_SRC_DIR/codebuild/samples/securetunnel-linux.sh
22+
- $CODEBUILD_SRC_DIR/codebuild/samples/connect-custom-authorizer-linux.sh
2223
post_build:
2324
commands:
2425
- echo Build completed on `date`

samples/README.md

+36
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* [Raw Connect](#raw-connect)
88
* [x509 Credentials Provider Connect](#x509-credentials-provider-connect)
99
* [Windows Certificate MQTT Connect](#windows-certificate-mqtt-connect)
10+
* [Custom Authorizer Connect](#custom-authorizer-connect)
1011
* [Fleet provisioning](#fleet-provisioning)
1112
* [Shadow](#shadow)
1213
* [Jobs](#jobs)
@@ -387,6 +388,41 @@ Your Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-
387388
</pre>
388389
</details>
389390
391+
## Custom Authorizer Connect
392+
393+
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.
394+
395+
Your Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect.
396+
397+
<details>
398+
<summary>(see sample policy)</summary>
399+
<pre>
400+
{
401+
"Version": "2012-10-17",
402+
"Statement": [
403+
{
404+
"Effect": "Allow",
405+
"Action": [
406+
"iot:Connect"
407+
],
408+
"Resource": [
409+
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
410+
]
411+
}
412+
]
413+
}
414+
</pre>
415+
</details>
416+
417+
To run the Custom Authorizer Connect sample use the following command:
418+
419+
``` sh
420+
./custom-authorizer-connect --endpoint <endpoint> --ca_file <path to root CA> --custom_auth_authorizer_name <authorizer name>
421+
```
422+
423+
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.
424+
425+
390426
## Shadow
391427

392428
This sample uses the AWS IoT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
cmake_minimum_required(VERSION 3.1)
2+
# note: cxx-17 requires cmake 3.8, cxx-20 requires cmake 3.12
3+
project(custom-authorizer-connect CXX)
4+
5+
file(GLOB SRC_FILES
6+
"*.cpp"
7+
"../../utils/CommandLineUtils.cpp"
8+
"../../utils/CommandLineUtils.h"
9+
)
10+
11+
add_executable(${PROJECT_NAME} ${SRC_FILES})
12+
13+
set_target_properties(${PROJECT_NAME} PROPERTIES
14+
CXX_STANDARD 14)
15+
16+
#set warnings
17+
if (MSVC)
18+
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /WX /wd4068)
19+
else ()
20+
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wno-long-long -pedantic -Werror)
21+
endif ()
22+
23+
find_package(aws-crt-cpp REQUIRED)
24+
25+
target_link_libraries(${PROJECT_NAME} AWS::aws-crt-cpp)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
#include <aws/crt/Api.h>
6+
#include <aws/crt/UUID.h>
7+
8+
#include "../../utils/CommandLineUtils.h"
9+
10+
using namespace Aws::Crt;
11+
12+
int main(int argc, char *argv[])
13+
{
14+
15+
/************************ Setup the Lib ****************************/
16+
/*
17+
* Do the global initialization for the API.
18+
*/
19+
ApiHandle apiHandle;
20+
21+
/*********************** Parse Arguments ***************************/
22+
Utils::CommandLineUtils cmdUtils = Utils::CommandLineUtils();
23+
cmdUtils.RegisterProgramName("custom_authorizer_connect");
24+
cmdUtils.AddCommonMQTTCommands();
25+
cmdUtils.AddCommonCustomAuthorizerCommands();
26+
cmdUtils.RegisterCommand("client_id", "<str>", "Client id to use (optional, default='test-*')");
27+
const char **const_argv = (const char **)argv;
28+
cmdUtils.SendArguments(const_argv, const_argv + argc);
29+
30+
// Make a MQTT client and create a connection through a custom authorizer
31+
// Note: The data for the connection is gotten from cmdUtils
32+
// (see BuildDirectMQTTConnectionWithCustomAuthorizer for implementation)
33+
Aws::Iot::MqttClient client = Aws::Iot::MqttClient();
34+
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> connection =
35+
cmdUtils.BuildDirectMQTTConnectionWithCustomAuthorizer(&client);
36+
37+
// Get the client ID to send with the connection
38+
String clientId = cmdUtils.GetCommandOrDefault("client_id", String("test-") + Aws::Crt::UUID().ToString());
39+
40+
// Connect and then disconnect using the connection we created
41+
// (see SampleConnectAndDisconnect for implementation)
42+
cmdUtils.SampleConnectAndDisconnect(connection, clientId);
43+
return 0;
44+
}

samples/utils/CommandLineUtils.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,27 @@ namespace Utils
177177
RegisterCommand(m_cmd_topic, "<str>", "Topic to publish, subscribe to. (optional, default='test/topic')");
178178
}
179179

180+
void CommandLineUtils::AddCommonCustomAuthorizerCommands()
181+
{
182+
RegisterCommand(
183+
m_cmd_custom_auth_username,
184+
"<str>",
185+
"The name to send when connecting through the custom authorizer (optional)");
186+
RegisterCommand(
187+
m_cmd_custom_auth_authorizer_name,
188+
"<str>",
189+
"The name of the custom authorizer to connect to (optional but required for everything but custom "
190+
"domains)");
191+
RegisterCommand(
192+
m_cmd_custom_auth_authorizer_signature,
193+
"<str>",
194+
"The signature to send when connecting through a custom authorizer (optional)");
195+
RegisterCommand(
196+
m_cmd_custom_auth_password,
197+
"<str>",
198+
"The password to send when connecting through a custom authorizer (optional)");
199+
}
200+
180201
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> CommandLineUtils::BuildPKCS11MQTTConnection(
181202
Aws::Iot::MqttClient *client)
182203
{
@@ -392,6 +413,24 @@ namespace Utils
392413
return GetClientConnectionForMQTTConnection(client, &clientConfigBuilder);
393414
}
394415

416+
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> CommandLineUtils::BuildDirectMQTTConnectionWithCustomAuthorizer(
417+
Aws::Iot::MqttClient *client)
418+
{
419+
Aws::Crt::String auth_username = GetCommandOrDefault(m_cmd_custom_auth_username, "");
420+
Aws::Crt::String auth_authorizer_name = GetCommandOrDefault(m_cmd_custom_auth_authorizer_name, "");
421+
Aws::Crt::String auth_authorizer_signature = GetCommandOrDefault(m_cmd_custom_auth_authorizer_signature, "");
422+
Aws::Crt::String auth_password = GetCommandOrDefault(m_cmd_custom_auth_password, "");
423+
424+
Aws::Crt::String endpoint = GetCommandRequired(m_cmd_endpoint);
425+
426+
auto clientConfigBuilder = Aws::Iot::MqttClientConnectionConfigBuilder::NewDefaultBuilder();
427+
clientConfigBuilder.WithEndpoint(endpoint);
428+
clientConfigBuilder.WithCustomAuthorizer(
429+
auth_username, auth_authorizer_name, auth_authorizer_signature, auth_password);
430+
431+
return GetClientConnectionForMQTTConnection(client, &clientConfigBuilder);
432+
}
433+
395434
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> CommandLineUtils::BuildMQTTConnection()
396435
{
397436
if (!m_internal_client)
@@ -422,6 +461,10 @@ namespace Utils
422461
return BuildWebsocketMQTTConnection(&m_internal_client);
423462
}
424463
}
464+
else if (HasCommand(m_cmd_custom_auth_authorizer_name))
465+
{
466+
return BuildDirectMQTTConnectionWithCustomAuthorizer(&m_internal_client);
467+
}
425468
else
426469
{
427470
return BuildDirectMQTTConnection(&m_internal_client);

samples/utils/CommandLineUtils.h

+22
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ namespace Utils
153153
*/
154154
void AddCommonTopicMessageCommands();
155155

156+
/**
157+
* A helper function taht adds custom_auth_username, custom_auth_authorizer_name,
158+
* custom_auth_authorizer_signature and custom_auth_password commands
159+
*/
160+
void AddCommonCustomAuthorizerCommands();
161+
156162
/**
157163
* A helper function that builds and returns a PKCS11 direct MQTT connection.
158164
*
@@ -193,6 +199,18 @@ namespace Utils
193199
*/
194200
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> BuildDirectMQTTConnection(Aws::Iot::MqttClient *client);
195201

202+
/**
203+
* A helper function that builds and returns a direct MQTT connection that will connect through a
204+
* CustomAuthorizer.
205+
* @param client The client to use to make the connection
206+
*
207+
* Will get the required data from the CommandLineUtils from arguments defined in the
208+
* AddCommonCustomAuthorizerCommands. See mqtt/custom_authorizer_connect for example.
209+
* @return The created direct MQTT connection
210+
*/
211+
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> BuildDirectMQTTConnectionWithCustomAuthorizer(
212+
Aws::Iot::MqttClient *client);
213+
196214
/**
197215
* A helper function that builds and returns a MQTT connection automatically based
198216
* on the commands passed into CommandLineUtils. Will make a direct MQTT connection, PKCS11 MQTT connection,
@@ -247,5 +265,9 @@ namespace Utils
247265
const Aws::Crt::String m_cmd_topic = "topic";
248266
const Aws::Crt::String m_cmd_port_override = "port_override";
249267
const Aws::Crt::String m_cmd_help = "help";
268+
const Aws::Crt::String m_cmd_custom_auth_username = "custom_auth_username";
269+
const Aws::Crt::String m_cmd_custom_auth_authorizer_name = "custom_auth_authorizer_name";
270+
const Aws::Crt::String m_cmd_custom_auth_authorizer_signature = "custom_auth_authorizer_signature";
271+
const Aws::Crt::String m_cmd_custom_auth_password = "custom_auth_password";
250272
};
251273
} // namespace Utils

0 commit comments

Comments
 (0)