Skip to content

Commit

Permalink
Added custom authorizer sample (#423)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
TwistedTwigleg authored May 26, 2022
1 parent 7ff4354 commit bca2450
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .builder/actions/build_samples.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def run(self, env):
'samples/mqtt/websocket_connect',
'samples/mqtt/x509_credentials_provider_connect',
'samples/mqtt/windows_cert_connect',
'samples/mqtt/custom_authorizer_connect',
'samples/shadow/shadow_sync',
'samples/greengrass/basic_discovery',
'samples/identity/fleet_provisioning',
Expand Down Expand Up @@ -52,7 +53,7 @@ def run(self, env):
steps.append(['cmake',
'--build', build_path,
'--config', 'RelWithDebInfo'])

for sample_path in da_samples:
build_path = os.path.join('build', sample_path)
steps.append(['cmake',
Expand Down
21 changes: 21 additions & 0 deletions codebuild/samples/connect-custom-authorizer-linux.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash

set -e

env

pushd $CODEBUILD_SRC_DIR/samples/mqtt/custom_authorizer_connect

mkdir _build
cd _build
cmake -DCMAKE_PREFIX_PATH=/tmp/install ..
make -j

ENDPOINT=$(aws secretsmanager get-secret-value --secret-id "unit-test/endpoint" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')
AUTH_NAME=$(aws secretsmanager get-secret-value --secret-id "unit-test/authorizer-name" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')
AUTH_PASSWORD=$(aws secretsmanager get-secret-value --secret-id "unit-test/authorizer-password" --query "SecretString" | cut -f2 -d":" | sed -e 's/[\\\"\}]//g')

echo "Custom authorizer connect test"
./custom-authorizer-connect --endpoint $ENDPOINT --custom_auth_authorizer_name $AUTH_NAME --custom_auth_password $AUTH_PASSWORD

popd
1 change: 1 addition & 0 deletions codebuild/samples/linux-smoke-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ phases:
- $CODEBUILD_SRC_DIR/codebuild/samples/connect-websocket-linux.sh
- $CODEBUILD_SRC_DIR/codebuild/samples/pkcs11-connect-linux.sh
- $CODEBUILD_SRC_DIR/codebuild/samples/securetunnel-linux.sh
- $CODEBUILD_SRC_DIR/codebuild/samples/connect-custom-authorizer-linux.sh
post_build:
commands:
- echo Build completed on `date`
2 changes: 1 addition & 1 deletion crt/aws-crt-cpp
36 changes: 36 additions & 0 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* [Raw Connect](#raw-connect)
* [x509 Credentials Provider Connect](#x509-credentials-provider-connect)
* [Windows Certificate MQTT Connect](#windows-certificate-mqtt-connect)
* [Custom Authorizer Connect](#custom-authorizer-connect)
* [Fleet provisioning](#fleet-provisioning)
* [Shadow](#shadow)
* [Jobs](#jobs)
Expand Down Expand Up @@ -387,6 +388,41 @@ Your Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-
</pre>
</details>
## Custom Authorizer Connect
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.
Your Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect.

<details>
<summary>(see sample policy)</summary>
<pre>
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Connect"
],
"Resource": [
"arn:aws:iot:<b>region</b>:<b>account</b>:client/test-*"
]
}
]
}
</pre>
</details>

To run the Custom Authorizer Connect sample use the following command:

``` sh
./custom-authorizer-connect --endpoint <endpoint> --ca_file <path to root CA> --custom_auth_authorizer_name <authorizer name>
```

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.


## Shadow

This sample uses the AWS IoT
Expand Down
25 changes: 25 additions & 0 deletions samples/mqtt/custom_authorizer_connect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.1)
# note: cxx-17 requires cmake 3.8, cxx-20 requires cmake 3.12
project(custom-authorizer-connect CXX)

file(GLOB SRC_FILES
"*.cpp"
"../../utils/CommandLineUtils.cpp"
"../../utils/CommandLineUtils.h"
)

add_executable(${PROJECT_NAME} ${SRC_FILES})

set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 14)

#set warnings
if (MSVC)
target_compile_options(${PROJECT_NAME} PRIVATE /W4 /WX /wd4068)
else ()
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wno-long-long -pedantic -Werror)
endif ()

find_package(aws-crt-cpp REQUIRED)

target_link_libraries(${PROJECT_NAME} AWS::aws-crt-cpp)
44 changes: 44 additions & 0 deletions samples/mqtt/custom_authorizer_connect/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/crt/Api.h>
#include <aws/crt/UUID.h>

#include "../../utils/CommandLineUtils.h"

using namespace Aws::Crt;

int main(int argc, char *argv[])
{

/************************ Setup the Lib ****************************/
/*
* Do the global initialization for the API.
*/
ApiHandle apiHandle;

/*********************** Parse Arguments ***************************/
Utils::CommandLineUtils cmdUtils = Utils::CommandLineUtils();
cmdUtils.RegisterProgramName("custom_authorizer_connect");
cmdUtils.AddCommonMQTTCommands();
cmdUtils.AddCommonCustomAuthorizerCommands();
cmdUtils.RegisterCommand("client_id", "<str>", "Client id to use (optional, default='test-*')");
const char **const_argv = (const char **)argv;
cmdUtils.SendArguments(const_argv, const_argv + argc);

// Make a MQTT client and create a connection through a custom authorizer
// Note: The data for the connection is gotten from cmdUtils
// (see BuildDirectMQTTConnectionWithCustomAuthorizer for implementation)
Aws::Iot::MqttClient client = Aws::Iot::MqttClient();
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> connection =
cmdUtils.BuildDirectMQTTConnectionWithCustomAuthorizer(&client);

// Get the client ID to send with the connection
String clientId = cmdUtils.GetCommandOrDefault("client_id", String("test-") + Aws::Crt::UUID().ToString());

// Connect and then disconnect using the connection we created
// (see SampleConnectAndDisconnect for implementation)
cmdUtils.SampleConnectAndDisconnect(connection, clientId);
return 0;
}
43 changes: 43 additions & 0 deletions samples/utils/CommandLineUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,27 @@ namespace Utils
RegisterCommand(m_cmd_topic, "<str>", "Topic to publish, subscribe to. (optional, default='test/topic')");
}

void CommandLineUtils::AddCommonCustomAuthorizerCommands()
{
RegisterCommand(
m_cmd_custom_auth_username,
"<str>",
"The name to send when connecting through the custom authorizer (optional)");
RegisterCommand(
m_cmd_custom_auth_authorizer_name,
"<str>",
"The name of the custom authorizer to connect to (optional but required for everything but custom "
"domains)");
RegisterCommand(
m_cmd_custom_auth_authorizer_signature,
"<str>",
"The signature to send when connecting through a custom authorizer (optional)");
RegisterCommand(
m_cmd_custom_auth_password,
"<str>",
"The password to send when connecting through a custom authorizer (optional)");
}

std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> CommandLineUtils::BuildPKCS11MQTTConnection(
Aws::Iot::MqttClient *client)
{
Expand Down Expand Up @@ -392,6 +413,24 @@ namespace Utils
return GetClientConnectionForMQTTConnection(client, &clientConfigBuilder);
}

std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> CommandLineUtils::BuildDirectMQTTConnectionWithCustomAuthorizer(
Aws::Iot::MqttClient *client)
{
Aws::Crt::String auth_username = GetCommandOrDefault(m_cmd_custom_auth_username, "");
Aws::Crt::String auth_authorizer_name = GetCommandOrDefault(m_cmd_custom_auth_authorizer_name, "");
Aws::Crt::String auth_authorizer_signature = GetCommandOrDefault(m_cmd_custom_auth_authorizer_signature, "");
Aws::Crt::String auth_password = GetCommandOrDefault(m_cmd_custom_auth_password, "");

Aws::Crt::String endpoint = GetCommandRequired(m_cmd_endpoint);

auto clientConfigBuilder = Aws::Iot::MqttClientConnectionConfigBuilder::NewDefaultBuilder();
clientConfigBuilder.WithEndpoint(endpoint);
clientConfigBuilder.WithCustomAuthorizer(
auth_username, auth_authorizer_name, auth_authorizer_signature, auth_password);

return GetClientConnectionForMQTTConnection(client, &clientConfigBuilder);
}

std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> CommandLineUtils::BuildMQTTConnection()
{
if (!m_internal_client)
Expand Down Expand Up @@ -422,6 +461,10 @@ namespace Utils
return BuildWebsocketMQTTConnection(&m_internal_client);
}
}
else if (HasCommand(m_cmd_custom_auth_authorizer_name))
{
return BuildDirectMQTTConnectionWithCustomAuthorizer(&m_internal_client);
}
else
{
return BuildDirectMQTTConnection(&m_internal_client);
Expand Down
22 changes: 22 additions & 0 deletions samples/utils/CommandLineUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ namespace Utils
*/
void AddCommonTopicMessageCommands();

/**
* A helper function taht adds custom_auth_username, custom_auth_authorizer_name,
* custom_auth_authorizer_signature and custom_auth_password commands
*/
void AddCommonCustomAuthorizerCommands();

/**
* A helper function that builds and returns a PKCS11 direct MQTT connection.
*
Expand Down Expand Up @@ -193,6 +199,18 @@ namespace Utils
*/
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> BuildDirectMQTTConnection(Aws::Iot::MqttClient *client);

/**
* A helper function that builds and returns a direct MQTT connection that will connect through a
* CustomAuthorizer.
* @param client The client to use to make the connection
*
* Will get the required data from the CommandLineUtils from arguments defined in the
* AddCommonCustomAuthorizerCommands. See mqtt/custom_authorizer_connect for example.
* @return The created direct MQTT connection
*/
std::shared_ptr<Aws::Crt::Mqtt::MqttConnection> BuildDirectMQTTConnectionWithCustomAuthorizer(
Aws::Iot::MqttClient *client);

/**
* A helper function that builds and returns a MQTT connection automatically based
* on the commands passed into CommandLineUtils. Will make a direct MQTT connection, PKCS11 MQTT connection,
Expand Down Expand Up @@ -247,5 +265,9 @@ namespace Utils
const Aws::Crt::String m_cmd_topic = "topic";
const Aws::Crt::String m_cmd_port_override = "port_override";
const Aws::Crt::String m_cmd_help = "help";
const Aws::Crt::String m_cmd_custom_auth_username = "custom_auth_username";
const Aws::Crt::String m_cmd_custom_auth_authorizer_name = "custom_auth_authorizer_name";
const Aws::Crt::String m_cmd_custom_auth_authorizer_signature = "custom_auth_authorizer_signature";
const Aws::Crt::String m_cmd_custom_auth_password = "custom_auth_password";
};
} // namespace Utils

0 comments on commit bca2450

Please sign in to comment.