Skip to content

Secure Tunnel V2 WebSocket Protocol support #533

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 33 commits into from
Feb 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8ea7899
adapting to new secure tunnel api
sbSteveK Jan 31, 2023
2180949
new api integration wip
sbSteveK Feb 9, 2023
6f3d7a2
Secure tunnel expansion of api
sbSteveK Feb 10, 2023
ddea326
documentation
sbSteveK Feb 11, 2023
8d96699
sample
sbSteveK Feb 11, 2023
ed5f65a
Add onConnectionFailure callbacks
sbSteveK Feb 13, 2023
d17dbff
added stopped callback
sbSteveK Feb 14, 2023
05fe207
Added actual minimal securetunnelbuilder constructor
sbSteveK Feb 14, 2023
6039bfb
Secure Tunnel Sample
sbSteveK Feb 15, 2023
4a8ca9a
Clean up cmdUtils in sample
sbSteveK Feb 15, 2023
40fae03
pr fixes
sbSteveK Feb 21, 2023
33094c1
sample update
sbSteveK Feb 22, 2023
c8c3f50
fix memory leak in sample
sbSteveK Feb 22, 2023
8ae4a2b
pr fixes/changes
sbSteveK Feb 22, 2023
d491dac
Merge branch 'main' into secure-tunnel-multiplex
sbSteveK Feb 22, 2023
0fecccf
merge with main
sbSteveK Feb 22, 2023
794869f
don't zero optional members
sbSteveK Feb 22, 2023
87890ce
disable existing secure tunnel tests
sbSteveK Feb 22, 2023
d1d893e
actually remove old tests
sbSteveK Feb 23, 2023
4c0715d
fix CMakeLists.txt
sbSteveK Feb 23, 2023
3b35141
don't zero an optional
sbSteveK Feb 23, 2023
25ddd1b
typo
sbSteveK Feb 23, 2023
24f33c8
windows warnings as errors
sbSteveK Feb 23, 2023
c1e7602
expand stream stopped callback
sbSteveK Feb 23, 2023
cbe140a
finish implementing StreamStoppedData
sbSteveK Feb 23, 2023
da1c84a
fix warnings in sample
sbSteveK Feb 23, 2023
8ce6f03
doc fixes
sbSteveK Feb 23, 2023
c4ce894
update sample readme and add services to ci
sbSteveK Feb 23, 2023
8e878d9
User Guide
sbSteveK Feb 23, 2023
abff139
remove comments
sbSteveK Feb 23, 2023
21c3d4d
code review changes
sbSteveK Feb 23, 2023
8b14d0e
latest submodules
sbSteveK Feb 23, 2023
22f74d1
remove file
sbSteveK Feb 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ __Jump To:__
* [FAQ](./documents/FAQ.md)
* [Giving Feedback and Contributions](#Giving-Feedback-and-Contributions)
* [MQTT5 User Guide](./documents/MQTT5_Userguide.md)
* [Secure Tunnel User Guide](./documents/Secure_Tunnel_Userguide.md)


## Installation
Expand Down
2 changes: 1 addition & 1 deletion crt/aws-crt-cpp
Submodule aws-crt-cpp updated 2 files
+1 −1 VERSION
+1 −1 crt/aws-c-auth
165 changes: 165 additions & 0 deletions documents/Secure_Tunnel_Userguide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# Introduction
When devices are deployed behind restricted firewalls at remote sites, you need a way to gain access to those devices for troubleshooting, configuration updates, and other operational tasks. Use secure tunneling to establish bidirectional communication to remote devices over a secure connection that is managed by AWS IoT. Secure tunneling does not require updates to your existing inbound firewall rules, so you can keep the same security level provided by firewall rules at a remote site.

More information on the service and how to open, close, and manage secure tunnels can be found here: https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling.html

A sample is also provided and can be found here: https://github.com/aws/aws-iot-device-sdk-cpp-v2/tree/main/samples#secure-tunnel



# Getting started with Secure Tunnels
## How to Create a Secure Tunnel Client
Once a Secure Tunnel builder has been created, it is ready to make a Secure Tunnel client. Something important to note is that once a Secure Tunnel client is built and finalized, the configuration is immutable and cannot be changed. Further modifications to the Secure Tunnel builder will not change the settings of already created Secure Tunnel clients.

```cpp
// Create Secure Tunnel Builder
SecureTunnelBuilder builder = SecureTunnelBuilder(...);

// Build Secure Tunnel Client
std::shared_ptr<SecureTunnel> secureTunnel = builder.Build();

if (secureTunnel == nullptr)
{
fprintf(stdout, "Secure Tunnel creation failed.\n");
return -1;
}

// Start the secure tunnel connection
if (!secureTunnel->Start())
{
fprintf("Failed to start Secure Tunnel\n");
return -1;
}
```
## Callbacks

### OnConnectionSuccess
When the Secure Tunnel Client successfully connects with the Secure Tunnel service, this callback will return the available (if any) service ids.

### OnConnectionFailure
When a WebSocket upgrade request fails to connect, this callback will return an error code.

### OnConnectionShutdown
When the WebSocket connection shuts down, this callback will be invoked.

### OnSendDataComplete
When a message has been completely written to the socket, this callback will be invoked.

### OnMessageReceived
When a message is received on an open Secure Tunnel stream, this callback will return the message.

### OnStreamStarted
When a stream is started by a Source connected to the Destination, the Destination will invoke this callback and return the stream information.

### OnStreamStopped
When an open stream is closed, this callback will be invoked and return the stopped stream's information.

### OnSessionReset
When the Secure Tunnel service requests the Secure Tunnel client fully reset, this callback is invoked.

### OnStopped
When the Secure Tunnel has reached a fully stopped state this callback is invoked.

## Setting Secure Tunnel Callbacks
The Secure Tunnel client uses callbacks to keep the user updated on its status and pass along relavant information. These can be set up using the Secure Tunnel builder's With functions.

```cpp
// Create Secure Tunnel Builder
SecureTunnelBuilder builder = SecureTunnelBuilder(...);

// Setting the onMessageReceived callback using the builder
builder.WithOnMessageReceived([&](SecureTunnel *secureTunnel, const MessageReceivedEventData &eventData) {
{
std::shared_ptr<Message> message = eventData.message;
if (message->getServiceId().has_value()){
fprintf(
stdout,
"Message received on service id:'" PRInSTR "'\n",
AWS_BYTE_CURSOR_PRI(message->getServiceId().value()));
}

if(message->getPayload().has_value()){
fprintf(
stdout,
"Message has payload:'" PRInSTR "'\n",
AWS_BYTE_CURSOR_PRI(message->getPayload().value()));
}
}
});

// Build Secure Tunnel Client
std::shared_ptr<SecureTunnel> secureTunnel = builder.Build();

if (secureTunnel == nullptr)
{
fprintf(stdout, "Secure Tunnel creation failed.\n");
return -1;
}

// Start the secure tunnel connection
if (!secureTunnel->Start())
{
fprintf("Failed to start Secure Tunnel\n");
return -1;
}

// Messages received on a stream will now be printed to stdout.
```

# How to Start and Stop

## Start
Invoking `Start()` on the Secure Tunnel Client will put it into an active state where it recurrently establishes a connection to the configured Secure Tunnel endpoint using the provided [Client Access Token](https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling-concepts.html). If a [Client Token](https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling-concepts.html) is provided, the Secure Tunnel Client will use it. If a Client Token is not provided, the Secure Tunnel Client will automatically generate one for use on a reconnection attempts. The Client Token for any initial connection to the Secure Tunnel service **MUST** be unique. Reusing a Client Token from a previous connection will result in a failed connection to the Secure Tunnel Service.
```cpp
// Create Secure Tunnel Builder
SecureTunnelBuilder builder = SecureTunnelBuilder(...);

// Adding a client token to the builder
String clientToken;
builder.WithClientToken(clientToken.c_str());

// Build Secure Tunnel Client
std::shared_ptr<SecureTunnel> secureTunnel = builder.Build();

if (secureTunnel == nullptr)
{
fprintf(stdout, "Secure Tunnel creation failed.\n");
return -1;
}

// Start the secure tunnel connection
if (!secureTunnel->Start())
{
fprintf("Failed to start Secure Tunnel\n");
return -1;
}
```

## Stop
Invoking `Stop()` on the Secure Tunnel Client breaks the current connection (if any) and moves the client into an idle state.
```cpp
if(!secureTunnel->Stop()){
fprintf(stdout, "Failed to stop the Secure Tunnel connection session. Exiting..\n");
}
```

# Secure Tunnel Operations

## Send Message
The SendMessage operation takes a description of the Message you wish to send and returns a success/failure in the synchronous logic that kicks off the Send Message operation. When the message is fully written to the socket, the OnSendDataComplete callback will be invoked.

```cpp
Crt::String serviceId_string = "ssh";
Crt::String message_string = "any payload";

ByteCursor serviceId = ByteCursorFromString(serviceId_string);
ByteCursor payload = ByteCursorFromString(message_string);

// Create Message
std::shared_ptr<Message> message = std::make_shared<Message>();
message->withServiceId(serviceId);
message->withPayload(payload);

// Send Message
secureTunnel->SendMessage(message);
```
10 changes: 3 additions & 7 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@ using a permanent certificate set, replace the paths specified in the `--cert` a

## Secure Tunnel

This sample uses AWS IoT [Secure Tunneling](https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling.html) Service to connect a destination and a source with each other through the AWS Secure Tunnel endpoint using access tokens.
This sample uses AWS IoT [Secure Tunneling](https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling.html) Service to connect a destination and a source with each other through the AWS Secure Tunnel endpoint using access tokens using the [V2WebSocketProtocol](https://github.com/aws-samples/aws-iot-securetunneling-localproxy/blob/main/V2WebSocketProtocolGuide.md). [Secure Tunnel Userguide](https://github.com/aws/aws-iot-device-sdk-cpp-v2/blob/main/documents/Secure_Tunnel_Userguide.md)

Source: `samples/secure_tunneling/secure_tunnel`

Expand All @@ -986,17 +986,13 @@ Create a new secure tunnel in the AWS IoT console (https://console.aws.amazon.co
Provide the necessary arguments along with the destination access token and start the sample in destination mode (default).

``` sh
./secure_tunnel --endpoint <endpoint> --ca_file <path to root CA>
--cert <path to the certificate> --key <path to the private key>
--thing_name <thing name> --region <region> --access_token_file <path to destination access token>
./secure_tunnel --region <region> --access_token_file <path to destination access token>
```

Provide the necessary arguments along with the source access token and start a second sample in source mode by using the flag --localProxyModeSource.

``` sh
./secure_tunnel --endpoint <endpoint> --ca_file <path to root CA>
--cert <path to the certificate> --key <path to the private key>
--thing_name <thing name> --region <region> --access_token_file <path to source access token>
./secure_tunnel --region <region> --access_token_file <path to source access token>
--localProxyModeSource
```

Expand Down
Loading